History

Added GridSolutionsFramework.sln to source control.

StephenCWills committed 14 years ago

Commit c5f7ca6No parent (first commit)915 files · +335125 −-73Browse files

Showing the changes to Source/Libraries/TSFJavaLibrary/src/org (33 of 915 files). Show all

Unified · Split

33 files
  1. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/Measurement.java +287 −0
  2. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/MeasurementKey.java +143 −0
  3. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/AdvancedSubscribe.java +453 −0
  4. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SampleSubscriberConnectorListener.java +90 −0
  5. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SampleSubscriberListener.java +182 −0
  6. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SimpleSubscribe.java +111 −0
  7. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/CompactMeasurementParser.java +288 −0
  8. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/DataSubscriber.java +1212 −0
  9. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/GatewayMeasurementParser.java +56 −0
  10. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SignalIndexCache.java +128 −0
  11. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SubscriberConnector.java +356 −0
  12. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SubscriptionInfo.java +563 −0
  13. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/CompressionMode.java +40 −0
  14. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/DataPacketFlags.java +52 −0
  15. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/OperationalEncoding.java +54 −0
  16. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/OperationalModes.java +78 −0
  17. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/ServerCommand.java +82 −0
  18. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/ServerResponse.java +86 −0
  19. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MeasurementEvent.java +66 −0
  20. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MessageEvent.java +86 −0
  21. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MetadataEvent.java +91 −0
  22. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/StartTimeEvent.java +59 −0
  23. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberAdapter.java +69 −0
  24. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberConnectorAdapter.java +44 −0
  25. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberConnectorListener.java +47 −0
  26. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberEvent.java +60 −0
  27. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberListener.java +90 −0
  28. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/ArrayExtensions.java +195 −0
  29. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/InputStreamExtensions.java +73 −0
  30. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/Masks.java +92 −0
  31. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/NumberExtensions.java +132 −0
  32. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/StringExtensions.java +88 −0
  33. Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/TimeExtensions.java +65 −0
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/Measurement.java+287−0
@@ -0,0 +1,287 @@
1//******************************************************************************************************
2// Measurement.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf;
25
26import java.util.UUID;
27
28/**
29 * Fundamental data type used by the Time Series Framework.
30 */
31public class Measurement
32{
33 private int m_id;
34 private String m_source;
35 private UUID m_signalId;
36 private String m_tag;
37 private double m_value;
38 private double m_adder;
39 private double m_multiplier;
40 private long m_timestamp;
41 private int m_flags;
42
43 /**
44 * Creates a new instance.
45 */
46 public Measurement()
47 {
48 m_multiplier = 1;
49 }
50
51 /**
52 * Creates a new instance that is a copy of another instance.
53 *
54 * @param copy the measurement to be copied
55 */
56 public Measurement(Measurement copy)
57 {
58 m_id = copy.m_id;
59 m_source = copy.m_source;
60 m_signalId = copy.m_signalId;
61 m_tag = copy.m_tag;
62 m_value = copy.m_value;
63 m_adder = copy.m_adder;
64 m_multiplier = copy.m_multiplier;
65 m_timestamp = copy.m_timestamp;
66 m_flags = copy.m_flags;
67 }
68
69 /**
70 * Gets the point ID of the measurement, which is
71 * the suffix of the human-readable measurement key.
72 *
73 * @return the point ID of the measurement
74 * @see #setId(int)
75 */
76 public int getId()
77 {
78 return m_id;
79 }
80
81 /**
82 * Sets the point ID of the measurement.
83 *
84 * @param id the new value of the point ID
85 * @see #getId()
86 */
87 public void setId(int id)
88 {
89 m_id = id;
90 }
91
92 /**
93 * Gets the source of the measurement, which is
94 * the prefix of the human-readable measurement key.
95 *
96 * @return the source of the measurement
97 * @see #setSource(String)
98 */
99 public String getSource()
100 {
101 return m_source;
102 }
103
104 /**
105 * Sets the source of the measurement.
106 *
107 * @param source the new value of the source
108 * @see #getSource()
109 */
110 public void setSource(String source)
111 {
112 m_source = source;
113 }
114
115 /**
116 * Gets the measurement's globally unique identifier.
117 *
118 * @return the measurement's globally unique identifier
119 * @see #setSignalId(UUID)
120 */
121 public UUID getSignalId()
122 {
123 return m_signalId;
124 }
125
126 /**
127 * Sets the measurement's globally unique identifier.
128 *
129 * @param signalID the new value of the measurement's globally unique identifier
130 * @see #getSignalId()
131 */
132 public void setSignalId(UUID signalID)
133 {
134 m_signalId = signalID;
135 }
136
137 /**
138 * Gets the human-readable tag name that describes the measurement.
139 *
140 * @return the human readable tag name
141 * @see #setTag(String)
142 */
143 public String getTag()
144 {
145 return m_tag;
146 }
147
148 /**
149 * Sets the human-readable tag name.
150 *
151 * @param tag the new value of the human-readable tag name
152 * @see #getTag()
153 */
154 public void setTag(String tag)
155 {
156 m_tag = tag;
157 }
158
159 /**
160 * Gets the value of the measurement.
161 *
162 * @return the value of the measurement
163 * @see #setValue(double)
164 * @see #getAdjustedValue()
165 */
166 public double getValue()
167 {
168 return m_value;
169 }
170
171 /**
172 * Sets the value of the measurement.
173 *
174 * @param value the new value
175 * @see #getValue()
176 * @see #getAdjustedValue()
177 */
178 public void setValue(double value)
179 {
180 m_value = value;
181 }
182
183 /**
184 * Gets the additive value modifier.
185 *
186 * @return the additive value modifier
187 * @see #setAdder(double)
188 * @see #getAdjustedValue()
189 */
190 public double getAdder()
191 {
192 return m_adder;
193 }
194
195 /**
196 * Sets the additive value modifier.
197 *
198 * @param adder the new additive value modifier
199 * @see #getAdder()
200 * @see #getAdjustedValue()
201 */
202 public void setAdder(double adder)
203 {
204 m_adder = adder;
205 }
206
207 /**
208 * Gets the multiplicative value modifier.
209 *
210 * @return the multiplicative value modifier
211 * @see #setMultiplier(double)
212 * @see #getAdjustedValue()
213 */
214 public double getMultiplier()
215 {
216 return m_multiplier;
217 }
218
219 /**
220 * Sets the multiplicative value modifier.
221 *
222 * @param multiplier the new multiplicative value modifier
223 * @see #getMultiplier()
224 * @see #getAdjustedValue()
225 */
226 public void setMultiplier(double multiplier)
227 {
228 m_multiplier = multiplier;
229 }
230
231 /**
232 * Gets the timestamp of the measurement in ticks.
233 *
234 * @return the timestamp of the measurement
235 */
236 public long getTimestamp()
237 {
238 return m_timestamp;
239 }
240
241 /**
242 * Sets the timestamp of the measurement.
243 *
244 * @param timestamp the new timestamp
245 */
246 public void setTimestamp(long timestamp)
247 {
248 m_timestamp = timestamp;
249 }
250
251 /**
252 * Gets the flags which define the measurement's state.
253 *
254 * @return the measurement's state flags
255 */
256 public int getFlags()
257 {
258 return m_flags;
259 }
260
261 /**
262 * Sets the flags which define the measurement's state.
263 *
264 * @param flags the new state flags
265 */
266 public void setFlags(int flags)
267 {
268 m_flags = flags;
269 }
270
271 /**
272 * Gets the adjusted value of the measurement, which is the value
273 * of the measurement after applying the multiplicative and
274 * additive value modifiers. Mathematically defined as:
275 * <p>
276 * {@code AdjustedValue = (Multiplier * Value) + Adder}
277 *
278 * @return the value of the measurement after applying modifiers
279 * @see #getValue()
280 * @see #getAdder()
281 * @see #getMultiplier()
282 */
283 public double getAdjustedValue()
284 {
285 return m_value * m_multiplier + m_adder;
286 }
287}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/MeasurementKey.java+143−0
@@ -0,0 +1,143 @@
1//******************************************************************************************************
2// MeasurementKey.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf;
25
26import java.util.UUID;
27
28import org.gpa.tsf.util.StringExtensions;
29
30/**
31 * Represents a grouping of a measurement's globally unique identifier
32 * and the alternate human-readable identifier {@code SOURCE:ID}.
33 * @see Measurement
34 */
35public class MeasurementKey
36{
37 private UUID m_signalId;
38 private String m_source;
39 private int m_id;
40
41 /**
42 * Constructs a measurement key by grouping the given parameters.
43 *
44 * @param signalId the measurement's globally unique identifier
45 * @param source the measurement's source
46 * @param id the measurement's ID
47 * @throws IllegalArgumentException if the given {@code signalID} is {@code null}
48 * or the given {@code source} is {@code null} or empty
49 */
50 public MeasurementKey(UUID signalId, String source, int id)
51 {
52 if (signalId == null)
53 throw new IllegalArgumentException("signalId must not be null");
54
55 if (StringExtensions.isNullOrWhitespace(source))
56 throw new IllegalArgumentException("source must not be null or empty");
57
58 m_signalId = signalId;
59 m_source = source;
60 m_id = id;
61 }
62
63 /**
64 * Gets the globally unique identifier of the measurement.
65 *
66 * @return the measurement's globally unique identifier
67 * @see Measurement#getSignalId()
68 */
69 public UUID getSignalId()
70 {
71 return m_signalId;
72 }
73
74 /**
75 * Gets the source of the measurement.
76 *
77 * @return the measurement's source
78 * @see Measurement#getSource()
79 */
80 public String getSource()
81 {
82 return m_source;
83 }
84
85 /**
86 * Gets the simple numeric identifier of the measurement.
87 *
88 * @return the measurement's simple numeric identifier
89 * @see Measurement#getId()
90 */
91 public int getId()
92 {
93 return m_id;
94 }
95
96 /**
97 * Compares this object to the specified object. The result is
98 * true if and only if the argument is not {@code null} and is
99 * a {@code MeasurementKey} that contains the same signal ID as
100 * this object.
101 */
102 @Override
103 public boolean equals(Object obj)
104 {
105 MeasurementKey key;
106
107 if(obj == null || !(obj instanceof MeasurementKey))
108 return false;
109
110 key = (MeasurementKey)obj;
111 return m_signalId.equals(key.m_signalId);
112 }
113
114 /**
115 * Returns a hash code for this {@code MeasurementKey}.
116 */
117 @Override
118 public int hashCode()
119 {
120 return m_signalId.hashCode();
121 }
122
123 /**
124 * Creates a measurement key for the given measurement, if it has one.
125 * This method returns null if either the measurement's signal ID
126 * is null or the source is null or empty.
127 *
128 * @param measurement the measurement whose key is to be created
129 * @return the key for the given measurement
130 */
131 public static MeasurementKey getKey(Measurement measurement)
132 {
133 UUID signalId = measurement.getSignalId();
134 String source = measurement.getSource();
135 int id = measurement.getId();
136 MeasurementKey key = null;
137
138 if (signalId != null && StringExtensions.isNullOrWhitespace(source))
139 key = new MeasurementKey(signalId, source, id);
140
141 return key;
142 }
143}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/AdvancedSubscribe.java+453−0
@@ -0,0 +1,453 @@
1//******************************************************************************************************
2// AdvancedSubscribe.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.sample;
25
26import java.awt.GridBagConstraints;
27import java.awt.GridBagLayout;
28import java.awt.event.ActionEvent;
29import java.awt.event.ActionListener;
30import java.io.IOException;
31import java.io.OutputStream;
32import java.io.PrintStream;
33import java.net.SocketException;
34import java.nio.ByteBuffer;
35import java.nio.charset.Charset;
36
37import javax.swing.Box;
38import javax.swing.BoxLayout;
39import javax.swing.JApplet;
40import javax.swing.JButton;
41import javax.swing.JLabel;
42import javax.swing.JScrollPane;
43import javax.swing.JTextArea;
44import javax.swing.JTextField;
45import javax.swing.SwingUtilities;
46
47import org.gpa.tsf.transport.DataSubscriber;
48import org.gpa.tsf.transport.SubscriberConnector;
49import org.gpa.tsf.transport.SubscriptionInfo;
50import org.gpa.tsf.transport.event.SubscriberConnectorListener;
51
52/**
53 * Sample applet to demonstrate the more advanced use of the subscriber API.
54 *
55 * This application accepts the hostname and port of the publisher via text
56 * fields on the applet, connects to the publisher, subscribes, and displays
57 * information about the measurements it receives. It assumes that the
58 * publisher is providing fourteen measurements (PPA:1 through PPA:14) and
59 * will retry infinitely if it has any trouble connecting. It will also
60 * automatically reconnect if the connection is terminated.
61 *
62 * Measurements are transmitted via a separate UDP data channel.
63 */
64public class AdvancedSubscribe extends JApplet
65{
66 private Object m_connectLock;
67 private ActionListener m_connectListener;
68 private ActionListener m_disconnectListener;
69
70 private JScrollPane m_outputScrollPane;
71 private JTextArea m_outputTextArea;
72 private JLabel m_hostnameLabel;
73 private JLabel m_portLabel;
74 private JTextField m_hostnameTextField;
75 private JTextField m_portTextField;
76 private JButton m_connectButton;
77 private JButton m_disconnectButton;
78 private Box m_buttonBox;
79
80 private PrintStream m_outputStream;
81 private SubscriptionInfo m_subscriptionInfo;
82 private SubscriberConnector m_connector;
83 private DataSubscriber m_subscriber;
84
85 @Override
86 public void init()
87 {
88 GridBagConstraints constraints;
89
90 super.init();
91
92 // Initialize members
93 m_connectLock = new Object();
94 m_connectListener = createConnectListener();
95 m_disconnectListener = createDisconnectListener();
96
97 m_outputTextArea = createOutputTextArea();
98 m_outputScrollPane = new JScrollPane(m_outputTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
99 m_hostnameLabel = new JLabel("Hostname");
100 m_portLabel = new JLabel("Port");
101 m_hostnameTextField = createHostnameTextField();
102 m_portTextField = createPortTextField();
103 m_connectButton = createConnectButton();
104 m_disconnectButton = createDisconnectButton();
105 m_buttonBox = createButtonBox();
106
107 m_outputStream = createOutputStream();
108 m_subscriptionInfo = createSubscriptionInfo();
109 m_connector = createSubscriberConnector(m_subscriptionInfo, m_outputStream);
110 m_subscriber = createSubscriber();
111
112 // Component layout
113 getContentPane().setLayout(new GridBagLayout());
114
115 constraints = new GridBagConstraints();
116 constraints.fill = GridBagConstraints.BOTH;
117 constraints.gridwidth = 2;
118 constraints.weighty = 1.0;
119 getContentPane().add(m_outputScrollPane, constraints);
120
121 constraints = new GridBagConstraints();
122 constraints.gridy = 1;
123 constraints.weightx = 0.5;
124 getContentPane().add(m_hostnameLabel, constraints);
125
126 constraints = new GridBagConstraints();
127 constraints.gridx = 1;
128 constraints.gridy = 1;
129 constraints.weightx = 0.5;
130 getContentPane().add(m_portLabel, constraints);
131
132 constraints = new GridBagConstraints();
133 constraints.fill = GridBagConstraints.HORIZONTAL;
134 constraints.gridy = 2;
135 constraints.weightx = 0.5;
136 getContentPane().add(m_hostnameTextField, constraints);
137
138 constraints = new GridBagConstraints();
139 constraints.fill = GridBagConstraints.HORIZONTAL;
140 constraints.gridx = 1;
141 constraints.gridy = 2;
142 constraints.weightx = 0.5;
143 getContentPane().add(m_portTextField, constraints);
144
145 constraints = new GridBagConstraints();
146 constraints.anchor = GridBagConstraints.CENTER;
147 constraints.gridy = 3;
148 constraints.gridwidth = 2;
149 getContentPane().add(m_buttonBox, constraints);
150 }
151
152 // Creates the action listener used to connect to the publisher.
153 private ActionListener createConnectListener()
154 {
155 return new ActionListener()
156 {
157 @Override
158 public void actionPerformed(ActionEvent arg0)
159 {
160 // Set the hostname and port before attempting to connect
161 m_connector.setHostname(m_hostnameTextField.getText());
162 m_connector.setPort(Integer.parseInt(m_portTextField.getText()));
163
164 // Connect asynchronously so we don't hog the UI thread
165 connectAsync();
166 }
167 };
168 }
169
170 // Connects and subscribes to the publisher asynchronously.
171 private void connectAsync()
172 {
173 new Thread(new Runnable()
174 {
175 @Override
176 public void run()
177 {
178 // Lock the connect lock so we don't encounter
179 // synchronization issues between calls to connectAsync
180 // and disconnectAsync
181 synchronized (m_connectLock)
182 {
183 try
184 {
185 if (m_connector.connect(m_subscriber))
186 m_subscriber.subscribe(m_subscriptionInfo);
187 }
188 catch (SocketException ex)
189 {
190 ex.printStackTrace(m_outputStream);
191 }
192 }
193 }
194 }).start();
195 }
196
197 // Creates the disconnect listener used to disconnect from the publisher.
198 private ActionListener createDisconnectListener()
199 {
200 return new ActionListener()
201 {
202 @Override
203 public void actionPerformed(ActionEvent arg0)
204 {
205 // Disconnect asynchronously so we don't hog the UI thread
206 disconnectAsync();
207 }
208 };
209 }
210
211 // Disconnects from the publisher asynchronously.
212 private void disconnectAsync()
213 {
214 new Thread(new Runnable()
215 {
216 @Override
217 public void run()
218 {
219 // Cancel the connector first so it won't try
220 // to automatically reconnect for any reason
221 m_connector.cancel();
222
223 // Lock the connect lock so we don't encounter
224 // synchronization issues between calls to connectAsync
225 // and disconnectAsync
226 synchronized (m_connectLock)
227 {
228 // Disconnect from the publisher
229 m_subscriber.disconnect();
230
231 // Create a new subscriber connector since we cancelled the old one
232 m_connector = createSubscriberConnector(m_subscriptionInfo, m_outputStream);
233 }
234 }
235 }).start();
236 }
237
238 // Creates the text area to which we send our program output.
239 private JTextArea createOutputTextArea()
240 {
241 JTextArea outputTextArea = new JTextArea();
242 outputTextArea.setEditable(false);
243 outputTextArea.setLineWrap(true);
244 outputTextArea.setWrapStyleWord(true);
245 return outputTextArea;
246 }
247
248 // Creates the text field where the user enters the hostname.
249 private JTextField createHostnameTextField()
250 {
251 JTextField hostnameTextField = new JTextField("localhost");
252 hostnameTextField.addActionListener(m_connectListener);
253 return hostnameTextField;
254 }
255
256 // Creates the text field where the user enters the port number.
257 private JTextField createPortTextField()
258 {
259 JTextField portTextField = new JTextField("6170");
260 portTextField.addActionListener(m_connectListener);
261 return portTextField;
262 }
263
264 // Creates the button used to connect to the publisher.
265 private JButton createConnectButton()
266 {
267 JButton connectButton = new JButton("Connect");
268 connectButton.addActionListener(m_connectListener);
269 return connectButton;
270 }
271
272 // Creates the button used to disconnect from the publisher.
273 private JButton createDisconnectButton()
274 {
275 JButton disconnectButton = new JButton("Disconnect");
276 disconnectButton.addActionListener(m_disconnectListener);
277 return disconnectButton;
278 }
279
280 // Creates the box that contains the connect and disconnect buttons.
281 private Box createButtonBox()
282 {
283 Box buttonBox = new Box(BoxLayout.X_AXIS);
284 buttonBox.add(m_connectButton);
285 buttonBox.add(m_disconnectButton);
286 return buttonBox;
287 }
288
289 // Creates the output stream that writes to the text area.
290 private PrintStream createOutputStream()
291 {
292 return new PrintStream(new TextAreaOutputStream(m_outputTextArea));
293 }
294
295 // SubscriptionInfo is a helper object which allows the user
296 // to set up their subscription and resuse subscription settings.
297 private SubscriptionInfo createSubscriptionInfo()
298 {
299 SubscriptionInfo info = new SubscriptionInfo();
300
301 // The following filter expression formats are also available:
302 //
303 // - Signal ID list -
304 //info.setFilterExpression("7aaf0a8f-3a4f-4c43-ab43-ed9d1e64a255;" +
305 // "93673c68-d59d-4926-b7e9-e7678f9f66b4;" +
306 // "65ac9cf6-ae33-4ece-91b6-bb79343855d5;" +
307 // "3647f729-d0ed-4f79-85ad-dae2149cd432;" +
308 // "069c5e29-f78a-46f6-9dff-c92cb4f69371;" +
309 // "25355a7b-2a9d-4ef2-99ba-4dd791461379");
310 //
311 // - Filter pattern -
312 //info.setFilterExpression("FILTER ActiveMeasurements WHERE ID LIKE 'PPA:*'");
313 //info.setFilterExpression("FILTER ActiveMeasurements WHERE Device = 'SHELBY' AND SignalType = 'FREQ'");
314
315 info.setFilterExpression("PPA:1;PPA:2;PPA:3;PPA:4;PPA:5;PPA:6;PPA:7;PPA:8;PPA:9;PPA:10;PPA:11;PPA:12;PPA:13;PPA:14");
316
317 // To set up a remotely synchronized subscription, set this flag
318 // to true and add the framesPerSecond parameter to the
319 // ExtraConnectionStringParameters. Additionally, the following
320 // example demonstrates the use of some other useful parameters
321 // when setting up remotely synchronized subscriptions.
322 //
323 //info.setRemotelySynchronized(true);
324 //info.setExtraConnectionStringParameters("framesPerSecond=30;timeResolution=10000;downsamplingMethod=Closest");
325
326 info.setRemotelySynchronized(false);
327 info.setThrottled(false);
328
329 info.setUdpDataChannel(true);
330 info.setDataChannelLocalPort(9600);
331
332 info.setTimeIncluded(true);
333 info.setLagTime(3.0);
334 info.setLeadTime(1.0);
335 info.setLocalClockAsRealTime(false);
336 info.setMillisecondResolution(true);
337
338 return info;
339 }
340
341 // SubscriberConnector is another helper object which allows the
342 // user to modify settings for auto-reconnects and retry cycles.
343 private SubscriberConnector createSubscriberConnector(SubscriptionInfo info, PrintStream outputStream)
344 {
345 SubscriberConnector connector = new SubscriberConnector();
346 SubscriberConnectorListener listener = new SampleSubscriberConnectorListener(info, outputStream);
347
348 connector.setMaxRetries(-1);
349 connector.setRetryInterval(5000);
350 connector.setAutoReconnect(true);
351 connector.addSubscriberConnectorListener(listener);
352
353 return connector;
354 }
355
356 // Creates the data subscriber.
357 private DataSubscriber createSubscriber()
358 {
359 DataSubscriber subscriber = new DataSubscriber();
360 subscriber.addSubscriberListener(new SampleSubscriberListener(m_outputStream, m_outputStream));
361 return subscriber;
362 }
363
364 private static final long serialVersionUID = -787591661184215315L;
365
366 // OutputStream that, when wrapped by a
367 // PrintStream, allows for output to a JTextArea.
368 private class TextAreaOutputStream extends OutputStream
369 {
370 private ByteBuffer m_buffer;
371 private JTextArea m_outputArea;
372
373 public TextAreaOutputStream(JTextArea outputTextArea)
374 {
375 if (outputTextArea == null)
376 throw new IllegalArgumentException("outputTextArea must not be null");
377
378 m_buffer = ByteBuffer.allocate(2000);
379 m_outputArea = outputTextArea;
380 }
381
382 @Override
383 public void flush() throws IOException
384 {
385 m_buffer.flip();
386 append(Charset.defaultCharset().decode(m_buffer).toString());
387 m_buffer = m_buffer.compact();
388 }
389
390 @Override
391 public void write(byte[] b) throws IOException
392 {
393 write(b, 0, b.length);
394 }
395
396 @Override
397 public void write(byte[] b, int off, int len) throws IOException
398 {
399 int rem = m_buffer.remaining();
400
401 if (len <= rem)
402 {
403 m_buffer.put(b, off, len);
404
405 if (m_buffer.position() >= DumpThreshold)
406 flush();
407 }
408 else
409 {
410 m_buffer.put(b, off, rem);
411 flush();
412
413 for (int i = rem; i < len; i += m_buffer.capacity())
414 {
415 rem = Math.min(m_buffer.remaining(), len - i);
416 m_buffer.put(b, off + i, rem);
417 flush();
418 }
419 }
420 }
421
422 @Override
423 public void write(int b) throws IOException
424 {
425 m_buffer.put((byte)b);
426
427 if (m_buffer.position() >= DumpThreshold)
428 flush();
429 }
430
431 private void append(final String text)
432 {
433 SwingUtilities.invokeLater(new Runnable()
434 {
435 @Override
436 public void run()
437 {
438 StringBuilder textBuilder = new StringBuilder(m_outputArea.getText());
439
440 textBuilder.append(text);
441
442 while (textBuilder.length() > CharacterLimit)
443 textBuilder.delete(0, textBuilder.indexOf(System.lineSeparator()) + 1);
444
445 m_outputArea.setText(textBuilder.toString());
446 }
447 });
448 }
449
450 private static final int DumpThreshold = 50;
451 private static final int CharacterLimit = 8192;
452 }
453}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SampleSubscriberConnectorListener.java+90−0
@@ -0,0 +1,90 @@
1//******************************************************************************************************
2// SampleSubscriberConnectorListener.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.sample;
25
26import java.io.PrintStream;
27
28import org.gpa.tsf.transport.SubscriptionInfo;
29import org.gpa.tsf.transport.event.MessageEvent;
30import org.gpa.tsf.transport.event.SubscriberConnectorAdapter;
31import org.gpa.tsf.transport.event.SubscriberEvent;
32
33/**
34 * Sample listener for a subscriber connector.
35 *
36 * @see SubscriberConnector
37 */
38public class SampleSubscriberConnectorListener extends SubscriberConnectorAdapter
39{
40 private SubscriptionInfo m_info;
41 private PrintStream m_errorStream;
42
43 /**
44 * Constructs a new instance using the standard {@code System.err}
45 * print stream for displaying errors.
46 *
47 * @param info subscription info used to automatically
48 * resubscribe to the publisher
49 */
50 public SampleSubscriberConnectorListener(SubscriptionInfo info)
51 {
52 this(info, System.err);
53 }
54
55 /**
56 * Constructs a new instance.
57 *
58 * @param info subscription info used to automatically
59 * resubscribe to the publisher
60 * @param errorStream print stream used for displaying errors
61 */
62 public SampleSubscriberConnectorListener(SubscriptionInfo info, PrintStream errorStream)
63 {
64 if (info == null)
65 throw new IllegalArgumentException("info must not be null");
66
67 m_info = info;
68 m_errorStream = errorStream;
69 }
70
71 @Override
72 public void exceptionEncountered(MessageEvent evt)
73 {
74 if (m_errorStream != null)
75 evt.getException().printStackTrace(m_errorStream);
76 }
77
78 @Override
79 public void reconnected(SubscriberEvent evt)
80 {
81 try
82 {
83 evt.getSubscriber().subscribe(m_info);
84 }
85 catch (Exception ex)
86 {
87 ex.printStackTrace(m_errorStream);
88 }
89 }
90}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SampleSubscriberListener.java+182−0
@@ -0,0 +1,182 @@
1//******************************************************************************************************
2// SampleSubscriberListener.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/19/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.sample;
25
26import java.io.PrintStream;
27import java.text.DateFormat;
28import java.text.SimpleDateFormat;
29import java.util.Collection;
30import java.util.Iterator;
31
32import org.gpa.tsf.Measurement;
33import org.gpa.tsf.transport.DataSubscriber;
34import org.gpa.tsf.transport.event.MeasurementEvent;
35import org.gpa.tsf.transport.event.MessageEvent;
36import org.gpa.tsf.transport.event.SubscriberAdapter;
37import org.gpa.tsf.util.TimeExtensions;
38
39/**
40 * Sample listener class for the {@link DataSubscriber}.
41 *
42 * @see SimpleSubscribe
43 */
44public class SampleSubscriberListener extends SubscriberAdapter
45{
46 private PrintStream m_outputStream;
47 private PrintStream m_errorStream;
48 private int m_processCount;
49
50 /**
51 * Constructs a new sample subscriber listener using the standard
52 * {@link System.out} and {@link System.err} print streams.
53 */
54 public SampleSubscriberListener()
55 {
56 this(System.out, System.err);
57 }
58
59 /**
60 * Constructs a new sample subscriber listener using
61 * the given output stream and no error stream.
62 *
63 * @param outputStream the output stream to which messages will be written
64 * @throws IllegalArgumentException if {@code outputStream} is {@code null}
65 */
66 public SampleSubscriberListener(PrintStream outputStream)
67 {
68 this(outputStream, null);
69 }
70
71 /**
72 * Constructs a new sample subscriber litener using
73 * the given output stream and error stream.
74 *
75 * @param outputStream the output stream to which status messages will be written
76 * @param errorStream the error stream to which error messages will be written
77 * @throws IllegalArgumentException if {@code outputStream} is {@code null}
78 */
79 public SampleSubscriberListener(PrintStream outputStream, PrintStream errorStream)
80 {
81 if (outputStream == null)
82 throw new IllegalArgumentException("outputStream cannot be null");
83
84 m_outputStream = outputStream;
85 m_errorStream = errorStream;
86 }
87
88 /**
89 * Writes status messages from the {@link DataSubscriber} to the output stream.
90 */
91 @Override
92 public void statusMessageReceived(MessageEvent evt)
93 {
94 m_outputStream.println(evt.getMessage());
95 m_outputStream.println();
96 }
97
98 /**
99 * Writes the stack trace of exceptions encountered
100 * by the {@link DataSubscriber} to the error stream.
101 */
102 @Override
103 public void exceptionEncountered(MessageEvent evt)
104 {
105 if (m_errorStream != null)
106 {
107 evt.getException().printStackTrace(m_errorStream);
108 m_errorStream.println();
109 }
110 }
111
112 /**
113 * Writes information about measurements received from the
114 * {@link DataSubscriber} to the output stream every so often.
115 */
116 @Override
117 public void newMeasurementsReceived(MeasurementEvent evt)
118 {
119 Collection<Measurement> newMeasurements = evt.getMeasurements();
120
121 DataSubscriber subscriber = null;
122 Measurement firstMeasurement = null;
123 Measurement nextMeasurement = null;
124 Iterator<Measurement> iter = null;
125
126 DateFormat dateFormat;
127 String dateString;
128
129 // Only display messages every five
130 // seconds (assuming 30 calls per second)
131 if (m_processCount % 150 == 0)
132 {
133 if (evt.getSource() instanceof DataSubscriber)
134 subscriber = (DataSubscriber)evt.getSource();
135
136 if (newMeasurements.size() > 0)
137 {
138 firstMeasurement = newMeasurements.iterator().next();
139 iter = newMeasurements.iterator();
140 }
141
142 if (subscriber != null)
143 m_outputStream.println(subscriber.getTotalMeasurementsReceived() + " measurements received so far...");
144
145 if (firstMeasurement != null)
146 {
147 dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
148 dateString = dateFormat.format(TimeExtensions.fromTicks(firstMeasurement.getTimestamp()).getTime());
149 m_outputStream.println("Timestamp: " + dateString);
150 }
151
152 if (iter != null)
153 {
154 m_outputStream.println("Point\tValue");
155
156 while (iter.hasNext())
157 {
158 nextMeasurement = iter.next();
159 m_outputStream.println(nextMeasurement.getId() + "\t" + nextMeasurement.getValue());
160 }
161
162 m_outputStream.println();
163 }
164 }
165
166 m_processCount++;
167 }
168
169 /**
170 * Writes the message received when the {@link DataSubscriber}'s
171 * connection is terminated to the error stream.
172 */
173 @Override
174 public void connectionTerminated(MessageEvent evt)
175 {
176 if (m_errorStream != null)
177 {
178 m_errorStream.println(evt.getMessage());
179 m_errorStream.println();
180 }
181 }
182}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/SimpleSubscribe.java+111−0
@@ -0,0 +1,111 @@
1//******************************************************************************************************
2// SimpleSubscribe.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/19/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.sample;
25
26import java.io.IOException;
27import java.util.Scanner;
28
29import org.gpa.tsf.transport.DataSubscriber;
30import org.gpa.tsf.transport.SubscriptionInfo;
31
32/**
33 * Provides an example of how to use the Subscriber API.
34 *
35 * @see DataSubscriber
36 */
37public class SimpleSubscribe
38{
39 private static DataSubscriber s_subscriber;
40
41 /**
42 * Main method. Entry point into the program.
43 *
44 * @param args command line arguments
45 */
46 public static void main(String[] args)
47 {
48 String hostname;
49 int port;
50
51 // Ensure that the necessary
52 // command line arguments are given
53 if (args.length < 2)
54 {
55 System.err.println("Error: requires two command line arguments");
56 System.err.println(" 1. hostname of publisher");
57 System.err.println(" 2. port used to initiate connection");
58 return;
59 }
60
61 // Get hostname and port
62 hostname = args[0];
63 port = Integer.parseInt(args[1]);
64
65 // Run the subscriber
66 runSubscriber(hostname, port);
67
68 // Wait until user presses enter before quitting
69 waitForUserInput();
70
71 // Disconnect the subscriber to stop background threads
72 if (s_subscriber != null)
73 s_subscriber.disconnect();
74 }
75
76 // The proper procedure when creating and running a subscriber is:
77 // - Create subscriber
78 // - Add listeners
79 // - Connect to publisher
80 // - Subscribe
81 private static void runSubscriber(String hostname, int port)
82 {
83 try
84 {
85 s_subscriber = new DataSubscriber();
86 s_subscriber.addSubscriberListener(new SampleSubscriberListener());
87 s_subscriber.connect(hostname, port);
88 s_subscriber.subscribe(createSubscriptionInfo());
89 }
90 catch (IOException ex)
91 {
92 ex.printStackTrace();
93 }
94 }
95
96 // SubscriptionInfo is a helper object which allows the user
97 // to set up their subscription and reuse subscription settings
98 private static SubscriptionInfo createSubscriptionInfo()
99 {
100 SubscriptionInfo info = new SubscriptionInfo();
101 info.setFilterExpression("PPA:1;PPA:2;PPA:3;PPA:4;PPA:5;PPA:6;PPA:7;PPA:8;PPA:9;PPA:10;PPA:11;PPA:12;PPA:13;PPA:14");
102 return info;
103 }
104
105 // Waits for the user to press Enter before proceeding
106 private static void waitForUserInput()
107 {
108 Scanner scan = new Scanner(System.in);
109 scan.nextLine();
110 }
111}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/CompactMeasurementParser.java+288−0
@@ -0,0 +1,288 @@
1//******************************************************************************************************
2// CompactMeasurementParser.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26import java.nio.ByteBuffer;
27import java.util.ArrayList;
28import java.util.Collection;
29
30import org.gpa.tsf.Measurement;
31import org.gpa.tsf.MeasurementKey;
32import org.gpa.tsf.util.Masks;
33
34/**
35 * Implementation of {@link GatewayMeasurementParser} that parses
36 * measurements serialized using the compact measurement format.
37 */
38public class CompactMeasurementParser implements GatewayMeasurementParser
39{
40 private SignalIndexCache m_signalIndexCache;
41 private long[] m_baseTimeOffsets;
42 private boolean m_includeTime;
43 private boolean m_useMillisecondResolution;
44
45 /**
46 * Constructs a new compact measurement parser with the given signal index cache.
47 *
48 * @param signalIndexCache the cache used to compact measurement IDs during serialization
49 * @throws IllegalArgumentException if {@code signalIndexCache} is {@code null}
50 */
51 public CompactMeasurementParser(SignalIndexCache signalIndexCache)
52 {
53 this(signalIndexCache, null, true, false);
54 }
55
56 /**
57 * Constructs a new compact measurement parser with the
58 * given signal index cache and base time offsets.
59 *
60 * @param signalIndexCache the cache used to compact measurement IDs during serialization
61 * @param baseTimeOffsets the offsets used to compact measurement timestamps during serialization
62 * @param includeTime indicates whether timestamps were included when serializing the measurements
63 * @param useMillisecondResolution determines whether measurement timestamps were further compacted
64 * during serialization by specifying them to be in millisecond resolution
65 * @throws IllegalArgumentException if {@code signalIndexCache} is {@code null}
66 */
67 public CompactMeasurementParser(SignalIndexCache signalIndexCache, long[] baseTimeOffsets, boolean includeTime, boolean useMillisecondResolution)
68 {
69 if(signalIndexCache == null)
70 throw new IllegalArgumentException("signalIndexCache cannot be null");
71
72 m_signalIndexCache = signalIndexCache;
73 m_baseTimeOffsets = baseTimeOffsets;
74 m_includeTime = includeTime;
75 m_useMillisecondResolution = useMillisecondResolution;
76 }
77
78 /**
79 * Parses a collection of serialized measurements.
80 */
81 @Override
82 public Collection<Measurement> parseMeasurements(byte[] serializedMeasurements, int offset, int length)
83 {
84 return parseMeasurements(ByteBuffer.wrap(serializedMeasurements, offset, length));
85 }
86
87 /**
88 * Parses a collection of serialized measurements.
89 */
90 @Override
91 public Collection<Measurement> parseMeasurements(ByteBuffer serializedMeasurementBuffer)
92 {
93 Collection<Measurement> measurements = new ArrayList<Measurement>();
94 Measurement parsedMeasurement;
95
96 // Parsed from serialized measurement
97 byte compactFlags;
98 short signalIndex;
99 float measurementValue;
100 long timestamp = 0L;
101
102 // Used for base time offsets
103 boolean usingBaseTimeOffset;
104 int timeIndex;
105
106 // Obtained from signal index cache
107 MeasurementKey key;
108
109 while (serializedMeasurementBuffer.hasRemaining())
110 {
111 // Get and validate compact measurement flags
112 compactFlags = serializedMeasurementBuffer.get();
113 usingBaseTimeOffset = (compactFlags & CompactBaseTimeOffsetFlag) != 0;
114 timeIndex = ((compactFlags & CompactTimeIndexFlag) != 0) ? 1 : 0;
115
116 if (usingBaseTimeOffset && (m_baseTimeOffsets == null || m_baseTimeOffsets[timeIndex] == 0))
117 break;
118
119 if (serializedMeasurementBuffer.remaining() + 1 < getMeasurementByteLength(usingBaseTimeOffset))
120 break;
121
122 // Get and validate signal index
123 signalIndex = serializedMeasurementBuffer.getShort();
124
125 if (!m_signalIndexCache.contains(signalIndex))
126 break;
127
128 // Get measurement value and timestamp
129 measurementValue = serializedMeasurementBuffer.getFloat();
130
131 if (m_includeTime)
132 {
133 if (!usingBaseTimeOffset)
134 {
135 timestamp = serializedMeasurementBuffer.getLong();
136 }
137 else if (!m_useMillisecondResolution)
138 {
139 timestamp = serializedMeasurementBuffer.getInt() & Masks.getLongMask(Integer.SIZE);
140 timestamp += m_baseTimeOffsets[timeIndex];
141 }
142 else
143 {
144 timestamp = serializedMeasurementBuffer.getShort() & Masks.getLongMask(Short.SIZE);
145 timestamp *= 10000;
146 timestamp += m_baseTimeOffsets[timeIndex];
147 }
148 }
149
150 // Construct the parsed measurement and add it to the collection
151 key = m_signalIndexCache.getMeasurementKey(signalIndex);
152 parsedMeasurement = new Measurement();
153
154 parsedMeasurement.setFlags(mapToFullFlags(compactFlags));
155 parsedMeasurement.setSignalId(key.getSignalId());
156 parsedMeasurement.setSource(key.getSource());
157 parsedMeasurement.setId(key.getId());
158 parsedMeasurement.setValue(measurementValue);
159 parsedMeasurement.setTimestamp(timestamp);
160
161 measurements.add(parsedMeasurement);
162 }
163
164 return measurements;
165 }
166
167 /**
168 * Gets the byte length of measurements parsed by this parser.
169 *
170 * @param usingBaseTimeOffset If false, measurement timestamps are 8 bytes; otherwise, they're smaller.
171 * This value is determined at serialization time for each individual measurement, so the value
172 * returned by this method may not be representative of all parsed measurements.
173 * @return the byte length of measurements parsed by this parser
174 */
175 public int getMeasurementByteLength(boolean usingBaseTimeOffset)
176 {
177 int byteLength = 7;
178
179 if (m_includeTime)
180 {
181 if (!usingBaseTimeOffset)
182 byteLength += 8;
183 else if(!m_useMillisecondResolution)
184 byteLength += 4;
185 else
186 byteLength += 2;
187 }
188
189 return byteLength;
190 }
191
192 // Maps the 8-bit compact flag format to the 32-bit full flag format.
193 private int mapToFullFlags(byte compactFlags)
194 {
195 int fullFlags = 0;
196
197 if ((compactFlags & CompactDataRangeFlag) != 0)
198 fullFlags |= DataRangeMask;
199
200 if ((compactFlags & CompactDataQualityFlag) != 0)
201 fullFlags |= DataQualityMask;
202
203 if ((compactFlags & CompactTimeQualityFlag) != 0)
204 fullFlags |= TimeQualityMask;
205
206 if ((compactFlags & CompactSystemIssueFlag) != 0)
207 fullFlags |= SystemIssueMask;
208
209 if ((compactFlags & CompactCalculatedValueFlag) != 0)
210 fullFlags |= CalculatedValueMask;
211
212 if ((compactFlags & CompactDiscardedValueFlag) != 0)
213 fullFlags |= DiscardedValueMask;
214
215 return fullFlags;
216 }
217
218 /**
219 * A data range flag was set.
220 */
221 public static final byte CompactDataRangeFlag = 0x01;
222
223 /**
224 * A data quality flag was set.
225 */
226 public static final byte CompactDataQualityFlag = 0x02;
227
228 /**
229 * A time quality flag was set.
230 */
231 public static final byte CompactTimeQualityFlag = 0x04;
232
233 /**
234 * A system flag was set.
235 */
236 public static final byte CompactSystemIssueFlag = 0x08;
237
238 /**
239 * Calculated value bit was set.
240 */
241 public static final byte CompactCalculatedValueFlag = 0x10;
242
243 /**
244 * Discarded value bit was set.
245 */
246 public static final byte CompactDiscardedValueFlag = 0x20;
247
248 /**
249 * Compact measurement timestamp was serialized using base time offset when set.
250 */
251 public static final byte CompactBaseTimeOffsetFlag = 0x40;
252
253 /**
254 * Use odd time index (i.e., 1) when bit is set; even time index (i.e., 0) when bit is clear.
255 */
256 public static final byte CompactTimeIndexFlag = (byte)0x80;
257
258 /**
259 * Mask over the data range flags.
260 */
261 public static final int DataRangeMask = 0x000000FC;
262
263 /**
264 * Mask over the data quality flags.
265 */
266 public static final int DataQualityMask = 0x0000EF03;
267
268 /**
269 * Mask over the time quality flags.
270 */
271 public static final int TimeQualityMask = 0x00BF0000;
272
273 /**
274 * Mask over the system issue flags.
275 */
276 public static final int SystemIssueMask = 0xE0000000;
277
278 /**
279 * Mask over the calculated value bit.
280 */
281 public static final int CalculatedValueMask = 0x00001000;
282
283 /**
284 * Mask over the dicarded value bit.
285 */
286 public static final int DiscardedValueMask = 0x00400000;
287
288}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/DataSubscriber.java+1212−0
@@ -0,0 +1,1212 @@
1//******************************************************************************************************
2// DataSubscriber.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26import java.io.ByteArrayInputStream;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.OutputStream;
30import java.net.DatagramPacket;
31import java.net.DatagramSocket;
32import java.net.InetAddress;
33import java.net.Socket;
34import java.net.SocketException;
35import java.net.UnknownHostException;
36import java.nio.ByteBuffer;
37import java.nio.ByteOrder;
38import java.nio.charset.Charset;
39import java.util.ArrayList;
40import java.util.Collection;
41import java.util.UUID;
42import java.util.concurrent.BlockingQueue;
43import java.util.concurrent.LinkedBlockingQueue;
44import java.util.concurrent.TimeUnit;
45import java.util.zip.GZIPInputStream;
46
47import org.gpa.tsf.Measurement;
48import org.gpa.tsf.transport.constant.CompressionMode;
49import org.gpa.tsf.transport.constant.DataPacketFlags;
50import org.gpa.tsf.transport.constant.OperationalEncoding;
51import org.gpa.tsf.transport.constant.OperationalModes;
52import org.gpa.tsf.transport.constant.ServerCommand;
53import org.gpa.tsf.transport.constant.ServerResponse;
54import org.gpa.tsf.transport.event.MeasurementEvent;
55import org.gpa.tsf.transport.event.MessageEvent;
56import org.gpa.tsf.transport.event.MetadataEvent;
57import org.gpa.tsf.transport.event.StartTimeEvent;
58import org.gpa.tsf.transport.event.SubscriberListener;
59import org.gpa.tsf.util.ArrayExtensions;
60import org.gpa.tsf.util.InputStreamExtensions;
61import org.gpa.tsf.util.Masks;
62import org.gpa.tsf.util.StringExtensions;
63
64/**
65 * Implementation of the Subscriber API that will connect
66 * to a data publisher for a data subscription.
67 */
68public class DataSubscriber
69{
70 private SubscriptionInfo m_currentSubscription;
71 private InetAddress[] m_allHostAddresses;
72 private InetAddress m_hostAddress;
73 private int m_operationalModes;
74 private Charset m_characterEncoding;
75 private boolean m_unsubscribing;
76 private boolean m_disconnecting;
77
78 // Statistics counters
79 private long m_totalCommandChannelBytesReceived;
80 private long m_totalDataChannelBytesReceived;
81 private long m_totalMeasurementsReceived;
82 private boolean m_connected;
83 private boolean m_subscribed;
84
85 // Measurement parsing
86 private SignalIndexCache m_signalIndexCache;
87 private long[] m_baseTimeOffsets;
88
89 // Command thread members
90 private Thread m_commandThread;
91 private BlockingQueue<byte[]> m_commandQueue;
92
93 // Callback thread members
94 private Thread m_callbackThread;
95 private BlockingQueue<Runnable> m_callbackQueue;
96
97 // Command channel
98 private Thread m_commandChannelResponseThread;
99 private Socket m_commandChannelSocket;
100
101 // Data channel
102 private Thread m_dataChannelResponseThread;
103 private DatagramSocket m_dataChannelSocket;
104
105 // Callbacks
106 private Collection<SubscriberListener> m_subscriberListeners;
107
108 /**
109 * Constructs a new data subscriber.
110 */
111 public DataSubscriber()
112 {
113 m_commandQueue = new LinkedBlockingQueue<byte[]>();
114 m_callbackQueue = new LinkedBlockingQueue<Runnable>();
115 m_subscriberListeners = new ArrayList<SubscriberListener>();
116
117 setOperationalModes(OperationalModes.UseCommonSerializationFormat | OperationalEncoding.Unicode | OperationalModes.CompressMetadata);
118 }
119
120 /**
121 * Adds the given listener to receive events from this subscriber.
122 * If the {@code listener} is {@code null}, no exception is thrown
123 * and no action is performed.
124 *
125 * @param subscriberListener the listener to be added
126 */
127 public void addSubscriberListener(SubscriberListener subscriberListener)
128 {
129 if (subscriberListener != null)
130 m_subscriberListeners.add(subscriberListener);
131 }
132
133 /**
134 * Removes the given listener so that it no longer receives events
135 * from this subscriber. This method performs no function, nor does
136 * it throw an exception, if {@code subscriberListener} was not
137 * previously added to this component. If {@code subscriberListener}
138 * is {@code null}, no exception is thrown and no action is performed.
139 *
140 * @param subscriberListener the listener to be removed
141 */
142 public void removeSubscriberListener(SubscriberListener subscriberListener)
143 {
144 if (subscriberListener != null)
145 m_subscriberListeners.remove(subscriberListener);
146 }
147
148 /**
149 * Gets the operational modes currently in use by this subscriber.
150 *
151 * @return the subscriber's operational modes
152 */
153 public int getOperationalModes()
154 {
155 return m_operationalModes;
156 }
157
158 /**
159 * Sets the operational modes of the subscriber.
160 * <p>
161 * The operational modes define a set of flags that can be used to
162 * indicate to the publisher how the subscriber wishes to communicate
163 * with it. This method will throw an {@code UnsupportedOperationException}
164 * if any of the following are true.
165 * <p>
166 * <ul>
167 * <li>{@link OperationalModes.UseCommonSerializationFormat} is unset</li>
168 * <li>{@link OperationalModes.CompressSignalIndexCache} is set</li>
169 * </ul>
170 *
171 * @param operationalModes the new operational modes
172 * @throws UnsupportedOperationException if an unsupported operational mode is detected
173 * @see OperationalModes
174 */
175 public void setOperationalModes(int operationalModes)
176 {
177 int operationalEncoding;
178
179 // .NET serialization format not supported
180 if ((operationalModes & OperationalModes.UseCommonSerializationFormat) == 0)
181 throw new UnsupportedOperationException("Cannot use .NET serialization format. Use common serialization format instead.");
182
183 // Update operational modes and character encoding
184 m_operationalModes = operationalModes;
185 operationalEncoding = operationalModes & OperationalModes.EncodingMask;
186
187 switch (operationalEncoding)
188 {
189 case OperationalEncoding.Unicode:
190 m_characterEncoding = Charset.forName("UTF-16LE");
191 break;
192
193 case OperationalEncoding.BigEndianUnicode:
194 m_characterEncoding = Charset.forName("UTF-16BE");
195 break;
196
197 case OperationalEncoding.UTF8:
198 m_characterEncoding = Charset.forName("UTF-8");
199 break;
200
201 case OperationalEncoding.OperatingSystemDefault:
202 m_characterEncoding = Charset.defaultCharset();
203 break;
204 }
205
206 // If subscriber is connected, send automatically
207 if (m_connected)
208 sendOperationalModes();
209 }
210
211 /**
212 * Connects to the publisher listening at the given hostname and port.
213 *
214 * @param hostname name or address of the machine hosting the publisher
215 * @param port the port that the publisher is listening on
216 * @throws IllegalStateException if the subscriber is already connected
217 * @throws IOException if an I/O error occurs when creating the socket
218 * @see #disconnect()
219 */
220 public void connect(String hostname, int port) throws IOException
221 {
222 m_totalCommandChannelBytesReceived = 0L;
223 m_totalDataChannelBytesReceived = 0L;
224 m_totalMeasurementsReceived = 0L;
225
226 if (m_connected)
227 throw new IllegalStateException("Subscriber is already connected; disconnect first");
228
229 m_commandChannelSocket = new Socket(hostname, port);
230 m_hostAddress = m_commandChannelSocket.getInetAddress();
231
232 if (m_hostAddress.isAnyLocalAddress())
233 m_hostAddress = InetAddress.getLocalHost();
234
235 try
236 {
237 m_allHostAddresses = InetAddress.getAllByName(m_hostAddress.getHostName());
238 }
239 catch (UnknownHostException ex)
240 {
241 m_allHostAddresses = new InetAddress[0];
242 }
243
244 startCommandThread();
245 startCallbackThread();
246 startCommandChannelResponseThread();
247
248 sendOperationalModes();
249 m_connected = true;
250 }
251
252 /**
253 * Disconnects from the data publisher. This method does not return
254 * until all connections have been closed and all threads spawned by
255 * the subscriber have shut down gracefully (with the exception of
256 * the thread that executes the connection terminated callback).
257 *
258 * @see #connect(String, int)
259 */
260 public void disconnect()
261 {
262 // Notify running threads that
263 // the subscriber is disconnecting
264 m_unsubscribing = true;
265 m_disconnecting = true;
266
267 try
268 {
269 // Close sockets so that threads using
270 // them can shut down gracefully
271 if (m_commandChannelSocket != null)
272 m_commandChannelSocket.close();
273 }
274 catch (IOException ex)
275 {
276 // Ignore exceptions and
277 // continue shutdown procedure
278 }
279
280 if (m_dataChannelSocket != null)
281 m_dataChannelSocket.close();
282
283 // Join with all threads to guarantee their completion
284 // before returning control to the caller
285 joinThread(m_commandThread);
286 joinThread(m_callbackThread);
287 joinThread(m_commandChannelResponseThread);
288 joinThread(m_dataChannelResponseThread);
289
290 // Empty queues so they can be used again later
291 m_commandQueue.clear();
292 m_callbackQueue.clear();
293
294 // Release references to threads and
295 // sockets that we are no longer using
296 m_commandThread = null;
297 m_callbackThread = null;
298 m_commandChannelResponseThread = null;
299 m_dataChannelResponseThread = null;
300 m_commandChannelSocket = null;
301 m_dataChannelSocket = null;
302
303 // Disconnect completed
304 m_unsubscribing = false;
305 m_subscribed = false;
306 m_disconnecting = false;
307 m_connected = false;
308 }
309
310 /**
311 * Subscribes to the signals specified by the
312 * filter expression in the {@code info} object.
313 *
314 * @param info subscription info used to configure the subscription
315 * @throws SocketException if, when defining a UDP data channel, the
316 * socket could not be opened, or the socket could not bind
317 * to the specified local port
318 * @see #unsubscribe()
319 */
320 public void subscribe(SubscriptionInfo info) throws SocketException
321 {
322 StringBuilder connectionStringBuilder = new StringBuilder();
323 byte[] connectionStringBytes;
324 ByteBuffer packetData;
325 int packetDataSize;
326
327 // Make sure to unsubscribe before attempting another
328 // subscription so we don't leave connections open
329 if (m_subscribed)
330 unsubscribe();
331
332 m_currentSubscription = new SubscriptionInfo(info);
333 m_totalMeasurementsReceived = 0L;
334
335 connectionStringBuilder.append("trackLatestMeasurements").append(info.isThrottled()).append(';');
336 connectionStringBuilder.append("includeTime=").append(info.isTimeIncluded()).append(';');
337 connectionStringBuilder.append("lagTime=").append(info.getLagTime()).append(';');
338 connectionStringBuilder.append("leadTime=").append(info.getLeadTime()).append(';');
339 connectionStringBuilder.append("useLocalClockAsRealTime=").append(info.isLocalClockAsRealTime()).append(';');
340 connectionStringBuilder.append("processingInterval=").append(info.getProcessingInterval()).append(';');
341 connectionStringBuilder.append("useMillisecondResolution=").append(info.isMillisecondResolution()).append(';');
342 connectionStringBuilder.append("assemblyInfo={source=TSF Java Library;version=0.9.0;buildDate=April 2012};");
343
344 if (!StringExtensions.isNullOrWhitespace(info.getFilterExpression()))
345 connectionStringBuilder.append("inputMeasurementKeys={").append(info.getFilterExpression()).append("};");
346
347 if (info.isUdpDataChannel())
348 {
349 m_dataChannelSocket = new DatagramSocket(info.getDataChannelLocalPort(), m_commandChannelSocket.getLocalAddress());
350 startDataChannelResponseThread();
351 connectionStringBuilder.append("dataChannel={localport=").append(info.getDataChannelLocalPort()).append("};");
352 }
353
354 if (!StringExtensions.isNullOrWhitespace(info.getStartTime()))
355 connectionStringBuilder.append("startTimeConstraint=").append(info.getStartTime()).append(';');
356
357 if (!StringExtensions.isNullOrWhitespace(info.getStopTime()))
358 connectionStringBuilder.append("stopTimeConstraint=").append(info.getStopTime()).append(';');
359
360 if (!StringExtensions.isNullOrWhitespace(info.getConstraintParameters()))
361 connectionStringBuilder.append("timeConstraintParameters=").append(info.getConstraintParameters()).append(';');
362
363 if (!StringExtensions.isNullOrWhitespace(info.getWaitHandleNames()))
364 {
365 connectionStringBuilder.append("waitHandleNames=").append(info.getWaitHandleNames()).append(';');
366 connectionStringBuilder.append("waitHandleTimeout=").append(info.getWaitHandleTimeout()).append(';');
367 }
368
369 if (!StringExtensions.isNullOrWhitespace(info.getExtraConnectionStringParameters()))
370 connectionStringBuilder.append(info.getExtraConnectionStringParameters()).append(';');
371
372 connectionStringBytes = connectionStringBuilder.toString().getBytes(m_characterEncoding);
373 packetDataSize = 5 + connectionStringBytes.length;
374 packetData = ByteBuffer.allocate(packetDataSize);
375
376 packetData.put((byte)(DataPacketFlags.Compact | (info.isRemotelySynchronized() ? DataPacketFlags.Synchronized : DataPacketFlags.NoFlags)));
377 packetData.putInt(connectionStringBytes.length);
378 packetData.put(connectionStringBytes);
379
380 sendServerCommand(ServerCommand.Subscribe, packetData.array(), 0, packetDataSize);
381 }
382
383 /**
384 * Gets a copy of the subscription info currently in use by the subscriber.
385 *
386 * @return copy of the subscription info currently in use by the subscriber
387 */
388 public SubscriptionInfo getCurrentSubscription()
389 {
390 return new SubscriptionInfo(m_currentSubscription);
391 }
392
393 /**
394 * Unsubscribes to stop receiving data from the publisher.
395 */
396 public void unsubscribe()
397 {
398 // Notify data channel response
399 // thread that we are unsubscribing
400 m_unsubscribing = true;
401
402 // Close socket so that data channel
403 // response thread can finish
404 if (m_dataChannelSocket != null)
405 m_dataChannelSocket.close();
406
407 // Join with data channel response thread to ensure
408 // that it finishes before returning from this method
409 joinThread(m_dataChannelResponseThread);
410
411 // Unsubscribe complete
412 m_unsubscribing = false;
413
414 // Notify server to stop sending data
415 sendServerCommand(ServerCommand.Unsubscribe);
416 }
417
418 /**
419 * Sends a command to the publisher.
420 *
421 * @param commandCode the {@link ServerCommand} code to be sent
422 */
423 public void sendServerCommand(byte commandCode)
424 {
425 sendServerCommand(commandCode, null, 0, 0);
426 }
427
428 /**
429 * Sends a command to the publisher over the command channel.
430 *
431 * @param commandCode the {@link ServerCommand} code to be sent
432 * @param data packet data to be sent to the server with the command
433 * @param offset offset in the buffer at which data sent to the server starts
434 * @param length amount of data in buffer that gets sent to the server
435 */
436 public void sendServerCommand(byte commandCode, byte[] data, int offset, int length)
437 {
438 final int PayloadHeaderSize = 8;
439
440 int packetSize = 1 + length;
441 int payloadSize = PayloadHeaderSize + packetSize;
442 byte[] command = new byte[payloadSize];
443
444 // Insert payload marker
445 command[0] = (byte)0xAA;
446 command[1] = (byte)0xBB;
447 command[2] = (byte)0xCC;
448 command[3] = (byte)0xDD;
449
450 // Insert packet size
451 command[4] = (byte)packetSize;
452 command[5] = (byte)(packetSize >> 8);
453 command[6] = (byte)(packetSize >> 16);
454 command[7] = (byte)(packetSize >> 24);
455
456 // Insert command code
457 command[8] = commandCode;
458
459 if (data != null)
460 ArrayExtensions.blockCopy(data, offset, command, PayloadHeaderSize + 1, length);
461
462 m_commandQueue.add(command);
463 }
464
465 /**
466 * Sends operational modes to the server.
467 *
468 * @see #setOperationalModes(int)
469 * @see #getOperationalModes()
470 */
471 public void sendOperationalModes()
472 {
473 byte[] commandData = ByteBuffer.allocate(4).putInt(m_operationalModes).array();
474 sendServerCommand(ServerCommand.DefineOperationalModes, commandData, 0, 4);
475 }
476
477 /**
478 * Gets the total number of bytes received on
479 * the command channel since last connection.
480 *
481 * @return the total number of bytes received on the command channel
482 */
483 public long getTotalCommandChannelBytesReceived()
484 {
485 return m_totalCommandChannelBytesReceived;
486 }
487
488 /**
489 * Gets the total number of bytes received on
490 * the data channel since last connection.
491 *
492 * @return the total number of bytes received on the data channel
493 */
494 public long getTotalDataChannelBytesReceived()
495 {
496 return m_totalDataChannelBytesReceived;
497 }
498
499 /**
500 * Gets the total number of measurements
501 * received since last subscription.
502 *
503 * @return the total number of measurements received
504 */
505 public long getTotalMeasurementsReceived()
506 {
507 return m_totalMeasurementsReceived;
508 }
509
510 /**
511 * Indicates whether the subscriber is
512 * currently connected to the publisher.
513 *
514 * @return flag indicating whether subscriber is connected
515 */
516 public boolean isConnected()
517 {
518 return m_connected;
519 }
520
521 /**
522 * Indicates whether the subscriber is
523 * currently subscribed to the publisher.
524 *
525 * @return flag indicating whether subscriber is subscribed
526 */
527 public boolean isSubscribed()
528 {
529 return m_subscribed;
530 }
531
532 /**
533 * Disconnects in case sockets are
534 * open or threads are still running.
535 */
536 @Override
537 protected void finalize() throws Throwable
538 {
539 if (m_connected)
540 disconnect();
541 }
542
543 // Joins with the given thread, checking for null
544 // and ignoring possible InterruptedExceptions.
545 private void joinThread(Thread th)
546 {
547 try
548 {
549 if (th != null)
550 th.join();
551 }
552 catch(InterruptedException ex)
553 {
554 // Ignore exception and
555 // continue shutdown procedure
556 }
557 }
558
559 // Creates and starts the command thread.
560 private void startCommandThread()
561 {
562 m_commandThread = new Thread(new Runnable()
563 {
564 @Override
565 public void run()
566 {
567 runCommandThread();
568 }
569 });
570
571 m_commandThread.start();
572 }
573
574 // Creates and starts the callback thread.
575 private void startCallbackThread()
576 {
577 m_callbackThread = new Thread(new Runnable()
578 {
579 @Override
580 public void run()
581 {
582 runCallbackThread();
583 }
584 });
585
586 m_callbackThread.start();
587 }
588
589 // Creates and starts the command channel response thread.
590 private void startCommandChannelResponseThread()
591 {
592 m_commandChannelResponseThread = new Thread(new Runnable()
593 {
594 @Override
595 public void run()
596 {
597 runCommandChannelResponseThread();
598 }
599 });
600
601 m_commandChannelResponseThread.start();
602 }
603
604 // Creates and starts the data channel response thread.
605 private void startDataChannelResponseThread()
606 {
607 m_dataChannelResponseThread = new Thread(new Runnable()
608 {
609 @Override
610 public void run()
611 {
612 runDataChannelResponseThread();
613 }
614 });
615
616 m_dataChannelResponseThread.start();
617 }
618
619 // Sends commands queued by other threads to the publisher.
620 private void runCommandThread()
621 {
622 try
623 {
624 OutputStream out = m_commandChannelSocket.getOutputStream();
625 byte[] command;
626
627 while (!m_disconnecting)
628 {
629 command = m_commandQueue.poll(PollTimeout, PollTimeoutUnit);
630
631 if (command != null)
632 out.write(command);
633 }
634 }
635 catch (InterruptedException ex)
636 {
637 // This thread is internal and
638 // should never be interrupted
639 throw new IllegalStateException(ex);
640 }
641 catch (IOException ex)
642 {
643 if (!m_disconnecting)
644 dispatchConnectionTerminated(ex);
645 }
646 }
647
648 // Executes callbacks queued by other threads.
649 private void runCallbackThread()
650 {
651 try
652 {
653 Runnable callback;
654
655 while (!m_disconnecting)
656 {
657 callback = m_callbackQueue.poll(PollTimeout, PollTimeoutUnit);
658
659 if (callback != null)
660 {
661 try
662 {
663 callback.run();
664 }
665 catch (Exception ex)
666 {
667 dispatchException(ex);
668 }
669 }
670 }
671 }
672 catch (InterruptedException ex)
673 {
674 // This thread is internal and
675 // should never be interrupted
676 throw new IllegalStateException(ex);
677 }
678 }
679
680 // Processes data received from the publisher on the command channel.
681 private void runCommandChannelResponseThread()
682 {
683 try
684 {
685 final int PayloadHeaderSize = 8;
686
687 InputStream in = m_commandChannelSocket.getInputStream();
688
689 ByteBuffer littleEndianBuffer = ByteBuffer.allocate(PayloadHeaderSize);
690 ByteBuffer bigEndianBuffer = ByteBuffer.allocate(MaxPacketSize);
691 int bytesRead;
692
693 int payloadBodySize;
694
695 littleEndianBuffer.order(ByteOrder.LITTLE_ENDIAN);
696 bigEndianBuffer.order(ByteOrder.BIG_ENDIAN);
697
698 while (true)
699 {
700 // Read the payload header from the input stream
701 bytesRead = InputStreamExtensions.read(in, littleEndianBuffer.array(), 0, PayloadHeaderSize);
702 m_totalCommandChannelBytesReceived += bytesRead;
703
704 if (m_disconnecting || bytesRead < PayloadHeaderSize)
705 break;
706
707 // Skip the 4-byte sync pattern
708 payloadBodySize = littleEndianBuffer.getInt(4);
709
710 // Increase the buffer size, if necessary
711 if (payloadBodySize > bigEndianBuffer.capacity())
712 bigEndianBuffer = ByteBuffer.allocate(payloadBodySize);
713
714 // Read the packet from the input stream
715 bytesRead = InputStreamExtensions.read(in, bigEndianBuffer.array(), 0, payloadBodySize);
716 m_totalCommandChannelBytesReceived += bytesRead;
717
718 if (m_disconnecting || bytesRead < payloadBodySize)
719 break;
720
721 // Set the limit on the buffer, process the
722 // buffer, and then rewind the buffer
723 bigEndianBuffer.limit(payloadBodySize);
724 processServerResponse(bigEndianBuffer);
725 bigEndianBuffer.rewind();
726 }
727 }
728 catch (IOException ex)
729 {
730 if (!m_disconnecting)
731 dispatchConnectionTerminated(ex);
732 }
733 }
734
735 // Processes data received by the publisher on the data channel.
736 private void runDataChannelResponseThread()
737 {
738 DatagramPacket packet = new DatagramPacket(new byte[MaxPacketSize], MaxPacketSize);
739
740 try
741 {
742 while (true)
743 {
744 m_dataChannelSocket.receive(packet);
745
746 if (m_unsubscribing)
747 break;
748
749 if (isValidHostAddress(packet.getAddress()))
750 {
751 m_totalDataChannelBytesReceived += packet.getLength();
752 processServerResponse(ByteBuffer.wrap(packet.getData(), packet.getOffset(), packet.getLength()));
753 }
754 }
755 }
756 catch (IOException ex)
757 {
758 if (!m_unsubscribing)
759 dispatchException(ex);
760 }
761 }
762
763 // Delegates data received from the publisher to the proper handler.
764 private void processServerResponse(ByteBuffer buffer)
765 {
766 byte responseCode = buffer.get();
767 byte commandCode = buffer.get();
768
769 // Skip length field in packet header,
770 // as length has already been determined
771 // by checking the payload header
772 buffer.getInt();
773
774 switch (responseCode)
775 {
776 case ServerResponse.Succeeded:
777 handleSucceeded(commandCode, buffer);
778 break;
779
780 case ServerResponse.Failed:
781 handleFailed(commandCode, buffer);
782 break;
783
784 case ServerResponse.DataPacket:
785 handleDataPacket(buffer);
786 break;
787
788 case ServerResponse.DataStartTime:
789 handleDataStartTime(buffer);
790 break;
791
792 case ServerResponse.ProcessingComplete:
793 handleProcessingComplete(buffer);
794 break;
795
796 case ServerResponse.UpdateSignalIndexCache:
797 handleUpdateSignalIndexCache(buffer);
798 break;
799
800 case ServerResponse.UpdateBaseTimes:
801 handleUpdateBaseTimes(buffer);
802 break;
803 }
804 }
805
806 // Handle success messages from the publisher.
807 private void handleSucceeded(byte commandCode, ByteBuffer buffer)
808 {
809 StringBuilder messageBuilder = new StringBuilder();
810 String hexCommandCode = Integer.toHexString(commandCode & Masks.getIntMask(Byte.SIZE));
811
812 switch (commandCode)
813 {
814 case ServerCommand.MetadataRefresh:
815 // Metadata refresh message is not sent with a
816 // message, but rather the metadata itself
817 handleMetadataRefresh(buffer);
818 break;
819
820 case ServerCommand.Subscribe:
821 case ServerCommand.Unsubscribe:
822 // Do not break on these messages because there is
823 // still an associated message to be processed
824 m_subscribed = (commandCode == ServerCommand.Subscribe);
825
826 case ServerCommand.Authenticate:
827 case ServerCommand.RotateCipherKeys:
828 // Each of these responses comes with a message that will
829 // be delivered to the user via the status message callback
830 messageBuilder.append("Received success code in response to server command 0x").append(hexCommandCode).append(": ");
831 messageBuilder.append(m_characterEncoding.decode(buffer));
832
833 dispatchStatusMessage(messageBuilder.toString());
834 break;
835
836 default:
837 // If we don't know what the message is, we can't interpret
838 // the data sent with the packet. Deliver an error message
839 // to the user via the exception encountered callback
840 messageBuilder.append("Received success code in response to unknown server command 0x").append(hexCommandCode);
841 dispatchException(new UnsupportedOperationException(messageBuilder.toString()));
842 break;
843 }
844 }
845
846 // Handle failure messages from the publisher.
847 private void handleFailed(byte commandCode, ByteBuffer buffer)
848 {
849 StringBuilder messageBuilder = new StringBuilder();
850 String hexCommandCode = Integer.toHexString(commandCode & Masks.getIntMask(Byte.SIZE));
851
852 messageBuilder.append("Received failure code from server command 0x").append(hexCommandCode).append(": ");
853 messageBuilder.append(m_characterEncoding.decode(buffer));
854 dispatchException(new RuntimeException(messageBuilder.toString()));
855 }
856
857 // Handle metadata received from the publisher.
858 private void handleMetadataRefresh(ByteBuffer buffer)
859 {
860 ByteBuffer buf = buffer;
861
862 if ((m_operationalModes & OperationalModes.CompressMetadata) != 0)
863 {
864 if ((m_operationalModes & OperationalModes.CompressionModeMask) == CompressionMode.GZIP)
865 {
866 buf = decompress(buffer);
867 }
868 }
869
870 dispatchMetadata(m_characterEncoding.decode(buf).toString());
871 }
872
873 // Handle data packets received from the publisher.
874 private void handleDataPacket(ByteBuffer buffer)
875 {
876 GatewayMeasurementParser parser;
877 Collection<Measurement> newMeasurements;
878
879 byte dataPacketFlags;
880 boolean compactFlag;
881 boolean syncFlag;
882 long frameLevelTimestamp = 0L;
883
884 SubscriptionInfo info;
885 boolean includeTime;
886 boolean useMillisecondResolution;
887
888 // Get relevante information about the current subscription
889 info = m_currentSubscription;
890 includeTime = info.isTimeIncluded();
891 useMillisecondResolution = info.isMillisecondResolution();
892
893 // Parse the data packet flags
894 dataPacketFlags = buffer.get();
895 compactFlag = (dataPacketFlags & DataPacketFlags.Compact) != 0;
896 syncFlag = (dataPacketFlags & DataPacketFlags.Synchronized) != 0;
897
898 // Gather statistics
899 m_totalMeasurementsReceived += buffer.getInt();
900
901 if (syncFlag)
902 {
903 frameLevelTimestamp = buffer.getLong();
904 includeTime = false;
905 }
906
907 if (compactFlag)
908 {
909 // If signal index cache is null, we
910 // cannot parse compact measurements
911 if (m_signalIndexCache == null)
912 return;
913
914 parser = new CompactMeasurementParser(m_signalIndexCache, m_baseTimeOffsets, includeTime, useMillisecondResolution);
915 }
916 else
917 {
918 // Not supported; dispatch exception and give up
919 dispatchException(new UnsupportedOperationException("Non-compact measurement format not supported"));
920 return;
921 }
922
923 try
924 {
925 // Parse measurements and expose them via listener
926 newMeasurements = parser.parseMeasurements(buffer);
927
928 if (syncFlag)
929 {
930 // Apply frame-level timestamp
931 for (Measurement newMeasurement : newMeasurements)
932 newMeasurement.setTimestamp(frameLevelTimestamp);
933 }
934
935 if (newMeasurements.size() > 0)
936 dispatchNewMeasurements(newMeasurements);
937 }
938 catch (Exception ex)
939 {
940 // Notify of exceptions during parse
941 dispatchException(ex);
942 }
943 }
944
945 // Handles data start time message received from publisher.
946 private void handleDataStartTime(ByteBuffer buffer)
947 {
948 dispatchDataStartTime(buffer.getLong());
949 }
950
951 // Handles processing complete message received from publisher.
952 private void handleProcessingComplete(ByteBuffer buffer)
953 {
954 dispatchProcessingComplete(m_characterEncoding.decode(buffer).toString());
955 }
956
957 // Updates the signal index cache with new values received from the publisher.
958 private void handleUpdateSignalIndexCache(ByteBuffer buffer)
959 {
960 ByteBuffer buf = buffer;
961 SignalIndexCache newCache = new SignalIndexCache();
962 int referenceCount;
963
964 short signalIndex;
965 UUID signalId;
966 int sourceSize;
967 String source;
968 int id;
969
970 if ((m_operationalModes & OperationalModes.CompressSignalIndexCache) != 0)
971 {
972 if ((m_operationalModes & OperationalModes.CompressionModeMask) == CompressionMode.GZIP)
973 {
974 buf = decompress(buffer);
975 }
976 }
977
978 // Skip 4-byte length and 16-byte subscriber ID
979 // We may need to parse these in the future...
980 buf.position(buf.position() + 20);
981
982 referenceCount = buf.getInt();
983
984 for (int i = 0; i < referenceCount; i++)
985 {
986 signalIndex = buf.getShort();
987 signalId = new UUID(buf.getLong(), buf.getLong());
988 sourceSize = buf.getInt();
989 source = m_characterEncoding.decode((ByteBuffer)buf.slice().limit(sourceSize)).toString();
990 id = ((ByteBuffer)buf.position(buf.position() + sourceSize)).getInt();
991
992 newCache.addMeasurementKey(signalIndex, signalId, source, id);
993 }
994
995 m_signalIndexCache = newCache;
996 }
997
998 // Updates the base times with new values received from the publisher.
999 private void handleUpdateBaseTimes(ByteBuffer buffer)
1000 {
1001 // Skip time index
1002 buffer.getInt();
1003
1004 m_baseTimeOffsets = new long[] { buffer.getLong(), buffer.getLong() };
1005 }
1006
1007 // Queues a status message callback.
1008 private void dispatchStatusMessage(final String message)
1009 {
1010 m_callbackQueue.add(new Runnable()
1011 {
1012 @Override
1013 public void run()
1014 {
1015 for (SubscriberListener listener : m_subscriberListeners)
1016 listener.statusMessageReceived(new MessageEvent(DataSubscriber.this, message));
1017 }
1018 });
1019 }
1020
1021 // Queues an exception encountered callback.
1022 private void dispatchException(final Exception exception)
1023 {
1024 m_callbackQueue.add(new Runnable()
1025 {
1026 @Override
1027 public void run()
1028 {
1029 for (SubscriberListener listener : m_subscriberListeners)
1030 listener.exceptionEncountered(new MessageEvent(DataSubscriber.this, exception));
1031 }
1032 });
1033 }
1034
1035 // Queues a data start time received callback.
1036 private void dispatchDataStartTime(final long dataStartTime)
1037 {
1038 m_callbackQueue.add(new Runnable()
1039 {
1040 @Override
1041 public void run()
1042 {
1043 for (SubscriberListener listener : m_subscriberListeners)
1044 listener.dataStartTimeReceived(new StartTimeEvent(DataSubscriber.this, dataStartTime));
1045 }
1046 });
1047 }
1048
1049 // Queues a metadata received callback.
1050 private void dispatchMetadata(final byte[] compressedMetadata)
1051 {
1052 m_callbackQueue.add(new Runnable()
1053 {
1054 @Override
1055 public void run()
1056 {
1057 for (SubscriberListener listener : m_subscriberListeners)
1058 listener.metadataReceived(new MetadataEvent(DataSubscriber.this, compressedMetadata));
1059 }
1060 });
1061 }
1062
1063 // Queues a metadata received callback.
1064 private void dispatchMetadata(final String xmlMetadata)
1065 {
1066 m_callbackQueue.add(new Runnable()
1067 {
1068 @Override
1069 public void run()
1070 {
1071 for (SubscriberListener listener : m_subscriberListeners)
1072 listener.metadataReceived(new MetadataEvent(DataSubscriber.this, xmlMetadata));
1073 }
1074 });
1075 }
1076
1077 // Queues a new measurements callback.
1078 private void dispatchNewMeasurements(final Collection<Measurement> newMeasurements)
1079 {
1080 m_callbackQueue.add(new Runnable()
1081 {
1082 @Override
1083 public void run()
1084 {
1085 for (SubscriberListener listener : m_subscriberListeners)
1086 listener.newMeasurementsReceived(new MeasurementEvent(DataSubscriber.this, newMeasurements));
1087 }
1088 });
1089 }
1090
1091 // Queues a processing complete callback.
1092 private void dispatchProcessingComplete(final String message)
1093 {
1094 m_callbackQueue.add(new Runnable()
1095 {
1096 @Override
1097 public void run()
1098 {
1099 for (SubscriberListener listener : m_subscriberListeners)
1100 listener.processingCompleteCallback(new MessageEvent(DataSubscriber.this, message));
1101 }
1102 });
1103 }
1104
1105 // Executes a connection terminated callback on a separate thread.
1106 private void dispatchConnectionTerminated(final Exception ex)
1107 {
1108 Thread connectionTerminatedThread = new Thread()
1109 {
1110 @Override
1111 public void run()
1112 {
1113 disconnect();
1114
1115 for (SubscriberListener listener : m_subscriberListeners)
1116 listener.connectionTerminated(new MessageEvent(DataSubscriber.this, ex));
1117 }
1118 };
1119
1120 connectionTerminatedThread.start();
1121 }
1122
1123 // Decompresses the data in the given buffer.
1124 private ByteBuffer decompress(ByteBuffer buffer)
1125 {
1126 ByteArrayInputStream inputStream = null;
1127 GZIPInputStream inflater = null;
1128 ArrayList<Byte> byteList;
1129 byte[] swap;
1130 int bytesRead;
1131
1132 try
1133 {
1134 inputStream = new ByteArrayInputStream(buffer.array(), buffer.position() + buffer.arrayOffset(), buffer.remaining());
1135 inflater = new GZIPInputStream(inputStream);
1136 byteList = new ArrayList<Byte>((int)(buffer.remaining() * 1.5));
1137 swap = new byte[1024];
1138
1139 do
1140 {
1141 // Decompress data and place it into swap array.
1142 bytesRead = inflater.read(swap, 0, swap.length);
1143
1144 // Swap the decompressed data into the byte list.
1145 for (int i = 0; i < bytesRead; i++)
1146 byteList.add(swap[i]);
1147 } while (bytesRead > 0);
1148
1149 // Increase swap size to contain the fully decompressed data.
1150 swap = new byte[byteList.size()];
1151
1152 // Copy the data into the swap array.
1153 for (int i = 0; i < swap.length; i++)
1154 swap[i] = byteList.get(i);
1155
1156 return ByteBuffer.wrap(swap);
1157 }
1158 catch (IOException ex)
1159 {
1160
1161 dispatchException(ex);
1162 }
1163 finally
1164 {
1165 try
1166 {
1167 // Attempt to close the input
1168 // streams to release resources.
1169 if (inflater != null)
1170 inflater.close();
1171
1172 if (inputStream != null)
1173 inputStream.close();
1174 } catch (IOException ex)
1175 {
1176 dispatchException(ex);
1177 }
1178 }
1179
1180 return buffer;
1181 }
1182
1183 // Determines whether the given IP address is
1184 // valid for the currently connected host.
1185 private boolean isValidHostAddress(InetAddress address)
1186 {
1187 // If it equals the cached host address, simply return
1188 if (m_hostAddress.equals(address))
1189 return true;
1190
1191 // Check all valid host addresses
1192 for (InetAddress hostAddress : m_allHostAddresses)
1193 {
1194 if (hostAddress.equals(address))
1195 {
1196 // Cache this address so we hopefully
1197 // don't have to loop every time
1198 m_hostAddress = hostAddress;
1199 return true;
1200 }
1201 }
1202
1203 // Address is not valid
1204 return false;
1205 }
1206
1207 // Maximum possible packet size to be received on the data channel.
1208 private static final int MaxPacketSize = 32767;
1209
1210 private static final long PollTimeout = 1L;
1211 private static final TimeUnit PollTimeoutUnit = TimeUnit.SECONDS;
1212}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/GatewayMeasurementParser.java+56−0
@@ -0,0 +1,56 @@
1//******************************************************************************************************
2// GatewayMeasurementParser.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26import java.nio.ByteBuffer;
27import java.util.Collection;
28
29import org.gpa.tsf.Measurement;
30
31/**
32 * Represents the interface used by the {@link DataSubscriber} to parse
33 * measurements from the publisher.
34 */
35public interface GatewayMeasurementParser
36{
37 /**
38 * Parses a collection of serialized measurements from a byte array.
39 *
40 * @param serializedMeasurements the serialized measurements to be parsed
41 * @param offset the offset into the array at which the collection starts
42 * @param length the byte length of the collection of serialized measurements
43 * @return the collection of parsed measurements
44 */
45 Collection<Measurement> parseMeasurements(byte[] serializedMeasurements, int offset, int length);
46
47 /**
48 * Parses a collection of serialized measurements from a byte buffer.
49 *
50 * @param serializedMeasurementBuffer The serialized measurements to be parsed.
51 * This method uses relative get operations on the buffer until there is
52 * no longer enough data left to parse any more measurements.
53 * @return the collection of parsed measurements
54 */
55 Collection<Measurement> parseMeasurements(ByteBuffer serializedMeasurementBuffer);
56}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SignalIndexCache.java+128−0
@@ -0,0 +1,128 @@
1//******************************************************************************************************
2// SignalIndexCache.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26import java.util.HashMap;
27import java.util.Map;
28import java.util.UUID;
29
30import org.gpa.tsf.MeasurementKey;
31
32/**
33 * Represents a cache used to map 16-bit indexes to {@link MeasurementKey}s
34 * in order to compact measurement IDs for the compact measurement format.
35 */
36public class SignalIndexCache
37{
38 private Map<Short, MeasurementKey> m_reference;
39 private Map<UUID, Short> m_signalIdCache;
40
41 /**
42 * Constructs a new signal index cache.
43 */
44 public SignalIndexCache()
45 {
46 m_reference = new HashMap<Short, MeasurementKey>();
47 m_signalIdCache = new HashMap<UUID, Short>();
48 }
49
50 /**
51 * Adds a measurement key to the signal index
52 * cache, identified by the given signal index.
53 *
54 * @param signalIndex the 16-bit index by which the
55 * measurement key can be retrieved from the cache
56 * @param signalId the measurement's globally unique identifier
57 * @param source the measurement's source
58 * @param id the measurement's simple numeric identifier
59 * @throws IllegalArgumentException if the given {@code signalID} is
60 * {@code null} or the given {@code source} is {@code null} or
61 * empty
62 */
63 public void addMeasurementKey(short signalIndex, UUID signalId, String source, int id)
64 {
65 addMeasurementKey(signalIndex, new MeasurementKey(signalId, source, id));
66 }
67
68 /**
69 * Adds a measurement key to the signal index
70 * cache, identified by the given signal index.
71 *
72 * @param signalIndex the 16-bit index by which the
73 * measurement key can be retrieved from the cache
74 * @param key the measurement key to be placed in the cache
75 */
76 public void addMeasurementKey(short signalIndex, MeasurementKey key)
77 {
78 m_reference.put(signalIndex, key);
79 m_signalIdCache.put(key.getSignalId(), signalIndex);
80 }
81
82 /**
83 * Empties the signal index cache.
84 */
85 public void clear()
86 {
87 m_reference.clear();
88 m_signalIdCache.clear();
89 }
90
91 /**
92 * Determines whether a measurement key exists
93 * in the cache for the given signal index.
94 *
95 * @param signalIndex the signal index to be searched for
96 * @return true if the signal index refers to
97 * a measurement key; false otherwise
98 */
99 public boolean contains(short signalIndex)
100 {
101 return m_reference.containsKey(signalIndex);
102 }
103
104 /**
105 * Gets the measurement key identified by the given signal index.
106 *
107 * @param signalIndex the signal index which identifies the measurement key
108 * @return the measurement key identified by the given signal index,
109 * or {@code null} if no mapping exists for the signal index
110 */
111 public MeasurementKey getMeasurementKey(short signalIndex)
112 {
113 return m_reference.get(signalIndex);
114 }
115
116 /**
117 * Provides a backwards mapping from the globally unique identifiers
118 * of the measurements whose keys are stored in the cache to the
119 * signal indexes that refer to them.
120 *
121 * @param signalId the measurement's globally unique identifier
122 * @return the signal index which identifies the measurement key
123 */
124 short getSignalIndex(UUID signalId)
125 {
126 return m_signalIdCache.get(signalId);
127 }
128}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SubscriberConnector.java+356−0
@@ -0,0 +1,356 @@
1//******************************************************************************************************
2// SubscriberConnector.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26import java.util.ArrayList;
27import java.util.Collection;
28
29import org.gpa.tsf.transport.event.MessageEvent;
30import org.gpa.tsf.transport.event.SubscriberAdapter;
31import org.gpa.tsf.transport.event.SubscriberConnectorListener;
32import org.gpa.tsf.transport.event.SubscriberEvent;
33import org.gpa.tsf.transport.event.SubscriberListener;
34
35/**
36 * Helper class to provide retry and auto-reconnect
37 * functionality to the subscriber.
38 *
39 * @see DataSubscriber
40 */
41public class SubscriberConnector
42{
43 Collection<SubscriberConnectorListener> m_listeners;
44 private DataSubscriber m_subscriber;
45 private SubscriberListener m_autoReconnectHandler;
46
47 private String m_hostname;
48 private int m_port;
49
50 private int m_maxRetries;
51 private int m_retryInterval;
52 private boolean m_autoReconnect;
53
54 private boolean m_cancel;
55
56 /**
57 * Constructs a new instance. The default configuration is infinite
58 * retries on a 2-second interval, and auto-reconnect is on.
59 */
60 public SubscriberConnector()
61 {
62 m_maxRetries = -1;
63 m_retryInterval = 2000;
64 m_autoReconnect = true;
65
66 m_listeners = new ArrayList<SubscriberConnectorListener>();
67 }
68
69 /**
70 * Adds the given listener to receive events from this subscriber
71 * connector. If the {@code listener} is {@code null}, no exception
72 * is thrown and no action is performed.
73 *
74 * @param listener the listener to be added
75 */
76 public void addSubscriberConnectorListener(SubscriberConnectorListener listener)
77 {
78 if (listener != null)
79 m_listeners.add(listener);
80 }
81
82 /**
83 * Removes the given listener so that it no longer receives events
84 * from this subscriber connector. This method performs no function,
85 * nor does it throw an exception, if {@code subscriberListener} was
86 * not previously added to this component. If {@code subscriberListener}
87 * is {@code null}, no exception is thrown and no action is performed.
88 *
89 * @param listener the listener to be removed
90 */
91 public void removeSubscriberConnectorListener(SubscriberConnectorListener listener)
92 {
93 if (listener != null)
94 m_listeners.remove(listener);
95 }
96
97 /**
98 * Begins the connection sequence.
99 *
100 * @param subscriber the subscriber to be connected
101 * @return connected status of the subscriber
102 * @throws IllegalArgumentException if {@code subscriber} is {@code null}
103 */
104 public boolean connect(DataSubscriber subscriber)
105 {
106 if (subscriber == null)
107 throw new IllegalArgumentException("subscriber must not be null");
108
109 // If we are no longer set to auto reconnect, we
110 // may need to detach from an existing subscriber.
111 if (!m_autoReconnect && m_subscriber != null)
112 {
113 m_subscriber.removeSubscriberListener(m_autoReconnectHandler);
114 m_subscriber = null;
115 }
116
117 // If we are set to auto reconnect and we are not currently
118 // attached to the given subscriber, we need to attach to the
119 // new subscriber.
120 if (m_autoReconnect && m_subscriber != subscriber)
121 {
122 if (m_subscriber != null)
123 m_subscriber.removeSubscriberListener(m_autoReconnectHandler);
124
125 if (m_autoReconnectHandler == null)
126 m_autoReconnectHandler = getNewAutoReconnectHandler();
127
128 m_subscriber = subscriber;
129 subscriber.addSubscriberListener(m_autoReconnectHandler);
130 }
131
132 // Attempt to connect for the given number of retries.
133 for (int i = 0; !m_cancel && (m_maxRetries == -1 || i < m_maxRetries); i++)
134 {
135 try
136 {
137 subscriber.connect(m_hostname, m_port);
138 break;
139 }
140 catch (Exception ex)
141 {
142 triggerExceptionEncounteredAsync(ex);
143 sleep(m_retryInterval);
144 }
145 }
146
147 // Return connection status of subscriber.
148 return subscriber.isConnected();
149 }
150
151 /**
152 * Cancels all current and future connection sequences.
153 */
154 public void cancel()
155 {
156 m_cancel = true;
157
158 if (m_subscriber != null)
159 m_subscriber.removeSubscriberListener(m_autoReconnectHandler);
160 }
161
162 /**
163 * Gets the hostname of the server this connector is connecting to.
164 *
165 * @return the hostname of the server
166 */
167 public String getHostname()
168 {
169 return m_hostname;
170 }
171
172 /**
173 * Sets the hostname of the server this connector is connecting to.
174 *
175 * @param hostname the new value for the hostname of the server
176 */
177 public void setHostname(String hostname)
178 {
179 m_hostname = hostname;
180 }
181
182 /**
183 * Gets the port that the publisher is listening on.
184 *
185 * @return the port that the publisher is listening on
186 */
187 public int getPort()
188 {
189 return m_port;
190 }
191
192 /**
193 * Sets the port that the publisher is listening on.
194 *
195 * @param port the new value for the port that the publisher
196 * is listening on
197 */
198 public void setPort(int port)
199 {
200 m_port = port;
201 }
202
203 /**
204 * Gets the maximum number of connection attempts to be made before
205 * giving up. A value of {@code -1} means an infinite number of retries.
206 *
207 * @return the maximum number of retries during a connection sequence
208 */
209 public int getMaxRetries()
210 {
211 return m_maxRetries;
212 }
213
214 /**
215 * Sets the maximum number of connection attempts to be made before
216 * giving up. A value of {@code -1} means an infinite number of retries.
217 *
218 * @param maxRetries the new value for the maximum number of retries
219 */
220 public void setMaxRetries(int maxRetries)
221 {
222 m_maxRetries = maxRetries;
223 }
224
225 /**
226 * Gets the interval of time, in milliseconds, between
227 * each connection attempt during a connection sequence.
228 *
229 * @return the retry interval, in milliseconds
230 */
231 public int getRetryInterval()
232 {
233 return m_retryInterval;
234 }
235
236 /**
237 * Sets the interval of time, in milliseconds, between
238 * each connection attempt during a connection sequence.
239 *
240 * @param retryInterval the new value for the retry interval,
241 * in milliseconds
242 */
243 public void setRetryInterval(int retryInterval)
244 {
245 m_retryInterval = retryInterval;
246 }
247
248 /**
249 * Gets the flag that indicates whether this connector should
250 * automatically attempt to reconnect the subscriber when the
251 * connection is terminated.
252 *
253 * @return the auto-reconnect flag
254 */
255 public boolean isAutoReconnect()
256 {
257 return m_autoReconnect;
258 }
259
260 /**
261 * Sets the flag that indicates whether this connector should
262 * automatically attempt to reconnect the subscriber when the
263 * connection is terminated.
264 *
265 * @param autoReconnect the new value for the auto-reconnect flag
266 */
267 public void setAutoReconnect(boolean autoReconnect)
268 {
269 m_autoReconnect = autoReconnect;
270 }
271
272 // Creates and returns a new auto-reconnect handler.
273 private SubscriberListener getNewAutoReconnectHandler()
274 {
275 return new SubscriberAdapter()
276 {
277 @Override
278 public void connectionTerminated(MessageEvent evt)
279 {
280 if (m_autoReconnect)
281 {
282 if (!m_cancel)
283 triggerExceptionEncountered(evt.getException());
284
285 connect(m_subscriber);
286
287 if (!m_cancel)
288 triggerReconnected();
289 }
290 }
291 };
292 }
293
294 // Triggers the exceptionEncountered event for
295 // all listeners subscribed to this connector.
296 // The event is triggered on a separate thread.
297 private void triggerExceptionEncounteredAsync(final Exception ex)
298 {
299 new Thread(new Runnable()
300 {
301 @Override
302 public void run()
303 {
304 triggerExceptionEncountered(ex);
305 }
306 }).start();
307 }
308
309 // Triggers the exceptionEncountered event for
310 // all listeners subscribed to this connector.
311 private void triggerExceptionEncountered(Exception encounteredException)
312 {
313 for (SubscriberConnectorListener listener : m_listeners)
314 {
315 try
316 {
317 listener.exceptionEncountered(new MessageEvent(this, encounteredException));
318 }
319 catch (Exception ex)
320 {
321 // Ignore exceptions encountered
322 // while reporting exceptions
323 }
324 }
325 }
326
327 // Triggers the reconnected event for all
328 // listeners subscribed to this connector.
329 private void triggerReconnected()
330 {
331 for (SubscriberConnectorListener listener : m_listeners)
332 {
333 try
334 {
335 listener.reconnected(new SubscriberEvent(this, m_subscriber));
336 }
337 catch (Exception ex)
338 {
339 triggerExceptionEncountered(ex);
340 }
341 }
342 }
343
344 // Puts the current thread to sleep for the given period of time.
345 private void sleep(long millis)
346 {
347 try
348 {
349 Thread.sleep(millis);
350 }
351 catch (InterruptedException ex)
352 {
353 triggerExceptionEncountered(ex);
354 }
355 }
356}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/SubscriptionInfo.java+563−0
@@ -0,0 +1,563 @@
1//******************************************************************************************************
2// SubscriptionInfo.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport;
25
26/**
27 * Configuration object for data subscriptions.
28 *
29 * @see DataSubscriber
30 * @see DataSubscriber#subscribe(SubscriptionInfo)
31 */
32public class SubscriptionInfo
33{
34 private String m_filterExpression;
35
36 private boolean m_remotelySynchronized;
37 private boolean m_throttled;
38
39 private boolean m_udpDataChannel;
40 private int m_dataChannelLocalPort;
41
42 private boolean m_timeIncluded;
43 private double m_lagTime;
44 private double m_leadTime;
45 private boolean m_localClockAsRealTime;
46 private boolean m_millisecondResolution;
47
48 private String m_startTime;
49 private String m_stopTime;
50 private String m_constraintParameters;
51 private int m_processingInterval;
52
53 private String m_waitHandleNames;
54 private int m_waitHandleTimeout;
55
56 private String m_extraConnectionStringParameters;
57
58 /**
59 * Constructs a new subscription info.
60 * The following default values have been overwritten.
61 *
62 * <ul>
63 * <li>{@code DataChannelLocalPort = 9500}</li>
64 * <li>{@code IncludeTime = true}</li>
65 * <li>{@code LagTime = 10.0}</li>
66 * <li>{@code LeadTime = 5.0}</li>
67 * <li>{@code ProcessingInterval = -1}</li>
68 * </ul>
69 */
70 public SubscriptionInfo()
71 {
72 m_dataChannelLocalPort = 9500;
73 m_timeIncluded = true;
74 m_lagTime = 10.0;
75 m_leadTime = 5.0;
76 m_processingInterval = -1;
77 }
78
79 /**
80 * Constructs a new subscription info object that
81 * is a copy of an existing subscription info object.
82 *
83 * @param info the subscription info to be copied
84 */
85 public SubscriptionInfo(SubscriptionInfo info)
86 {
87 m_filterExpression = info.m_filterExpression;
88
89 m_remotelySynchronized = info.m_remotelySynchronized;
90 m_throttled = info.m_throttled;
91
92 m_udpDataChannel = info.m_udpDataChannel;
93 m_dataChannelLocalPort = info.m_dataChannelLocalPort;
94
95 m_timeIncluded = info.m_timeIncluded;
96 m_lagTime = info.m_lagTime;
97 m_leadTime = info.m_leadTime;
98 m_localClockAsRealTime = info.m_localClockAsRealTime;
99 m_millisecondResolution = info.m_millisecondResolution;
100
101 m_startTime = info.m_startTime;
102 m_stopTime = info.m_stopTime;
103 m_constraintParameters = info.m_constraintParameters;
104 m_processingInterval = info.m_processingInterval;
105
106 m_waitHandleNames = info.m_waitHandleNames;
107 m_waitHandleTimeout = info.m_waitHandleTimeout;
108
109 m_extraConnectionStringParameters = info.m_extraConnectionStringParameters;
110 }
111
112 /**
113 * Gets the filter expression used to define which
114 * measurements are being requested by the subscriber.
115 *
116 * @return the filter expression
117 * @see #setFilterExpression(String)
118 */
119 public String getFilterExpression()
120 {
121 return m_filterExpression;
122 }
123
124 /**
125 * Sets the filter expression used to define which
126 * measurements are being requested by the subscriber.
127 *
128 * @param filterExpression the new value for the filter expression
129 * @see #getFilterExpression()
130 */
131 public void setFilterExpression(String filterExpression)
132 {
133 m_filterExpression = filterExpression;
134 }
135
136 /**
137 * Gets the flag that indicates whether the subscriber is requesting
138 * that its measurements be synchronized by the publisher.
139 *
140 * @return the flag that indicates whether the subscriber is requesting
141 * that its measurements be synchronized by the publisher
142 * @see #setRemotelySynchronized(boolean)
143 */
144 public boolean isRemotelySynchronized()
145 {
146 return m_remotelySynchronized;
147 }
148
149 /**
150 * Sets the flag that indicates whether the subscriber is requesting
151 * that its measurements be synchronized by the publisher.
152 *
153 * @param remotelySynchronized the new value of the flag that indicates
154 * whether the subscriber is requesting that its measurements be
155 * synchronized by the publisher
156 * @see #isRemotelySynchronized()
157 */
158 public void setRemotelySynchronized(boolean remotelySynchronized)
159 {
160 m_remotelySynchronized = remotelySynchronized;
161 }
162
163 /**
164 * Gets a flag indicating whether the
165 * requested position is to be throttled.
166 *
167 * @return flag indicating whether the subscription is throttled
168 * @see #setThrottled(boolean)
169 */
170 public boolean isThrottled()
171 {
172 return m_throttled;
173 }
174
175 /**
176 * Sets the flag which determines whether to
177 * request that the subscription be throttled.
178 *
179 * @param throttled the new value for the flag
180 * @see #isThrottled()
181 */
182 public void setThrottled(boolean throttled)
183 {
184 m_throttled = throttled;
185 }
186
187 /**
188 * Gets the flag which indicates whether the subscriber is
189 * requesting its data over a separate UDP data channel.
190 *
191 * @return the flag which indicates whether the subscriber is
192 * requesting its data over a separate UDP data channel
193 * @see #setUdpDataChannel(boolean)
194 */
195 public boolean isUdpDataChannel()
196 {
197 return m_udpDataChannel;
198 }
199
200 /**
201 * Sets the flag which determines whether the subscriber is
202 * requesting its data over a separate UDP data channel.
203 *
204 * @param udpDataChannel the new value for the flag
205 * @see #isUdpDataChannel()
206 */
207 public void setUdpDataChannel(boolean udpDataChannel)
208 {
209 m_udpDataChannel = udpDataChannel;
210 }
211
212 /**
213 * Gets the port that the UDP data channel binds to. This value is
214 * only used when the subscriber requests a separate UDP data channel.
215 *
216 * @return the local port that the UDP data channel binds to
217 * @see #setDataChannelLocalPort(int)
218 * @see #isUdpDataChannel()
219 */
220 public int getDataChannelLocalPort()
221 {
222 return m_dataChannelLocalPort;
223 }
224
225 /**
226 * Sets the port that the UDP data channel binds to. This value is
227 * only used when the subscriber requests a separate UDP data channel.
228 *
229 * @param dataChannelLocalPort
230 * @see #getDataChannelLocalPort()
231 * @see #setUdpDataChannel(boolean)
232 */
233 public void setDataChannelLocalPort(int dataChannelLocalPort)
234 {
235 m_dataChannelLocalPort = dataChannelLocalPort;
236 }
237
238 /**
239 * Gets the flag indicating whether timestamps are included in the
240 * data sent from the publisher. This value is ignored if the data
241 * is remotely synchronized.
242 *
243 * @return the flag indicating whether timestamps are included
244 * @see #setTimeIncluded(boolean)
245 */
246 public boolean isTimeIncluded()
247 {
248 return m_timeIncluded;
249 }
250
251 /**
252 * Sets the flag which determines whether timestamps are included in
253 * the data sent from the publisher. This value is ignored if the data
254 * is remotely synchronized.
255 *
256 * @param timeIncluded the new value for the flag
257 * @see #isTimeIncluded()
258 */
259 public void setTimeIncluded(boolean timeIncluded)
260 {
261 m_timeIncluded = timeIncluded;
262 }
263
264 /**
265 * Gets the allowed past time deviation tolerance, in seconds.
266 *
267 * @return the allowed past time deviation tolerance
268 * @see #setLagTime(double)
269 */
270 public double getLagTime()
271 {
272 return m_lagTime;
273 }
274
275 /**
276 * Sets the allowed past time deviation
277 * tolerance, in seconds (can be subscecond).
278 *
279 * @param lagTime the new value for the allowed
280 * past time deviation tolerance
281 * @see #getLagTime()
282 */
283 public void setLagTime(double lagTime)
284 {
285 m_lagTime = lagTime;
286 }
287
288 /**
289 * Gets the allowed future time deviation tolerance, in seconds.
290 *
291 * @return the allowed future time deviation tolerance
292 * @see #setLeadTime(double)
293 */
294 public double getLeadTime()
295 {
296 return m_leadTime;
297 }
298
299 /**
300 * Sets the allowed future time deviation
301 * tolerance, in seconds (can be subsecond).
302 *
303 * @param leadTime the new value for the allowed
304 * future time deviation tolerance
305 * @see #getLeadTime()
306 */
307 public void setLeadTime(double leadTime)
308 {
309 m_leadTime = leadTime;
310 }
311
312 /**
313 * Gets the flag that indicates whether the server's local clock is
314 * used as real-time. Otherwise, the timestamps of the measurements
315 * will be used as real-time.
316 *
317 * @return the flag that indicates whether the server's local clock
318 * is used as real-time
319 * @see #setLocalClockAsRealTime(boolean)
320 */
321 public boolean isLocalClockAsRealTime()
322 {
323 return m_localClockAsRealTime;
324 }
325
326 /**
327 * Sets the flag which determines whether the server's local clock is
328 * used as real-time. Otherwise, the timestamps of the measurements
329 * will be used as real-time.
330 *
331 * @param localClockAsRealTime the new value for the flag
332 * @see #isLocalClockAsRealTime()
333 */
334 public void setLocalClockAsRealTime(boolean localClockAsRealTime)
335 {
336 m_localClockAsRealTime = localClockAsRealTime;
337 }
338
339 /**
340 * Gets the flag that indicates whether measurement timestamps use
341 * millisecond resolution. Otherwise, they will use 100-nanosecond
342 * resolution.
343 * <p>
344 * This flag determines the size of the timestamps transmitted as
345 * part of the compact measurement format when the server is using
346 * base time offsets.
347 *
348 * @return the flag that indicates whether measurement timestamps use
349 * millisecond resolution
350 * @see #setMillisecondResolution(boolean)
351 */
352 public boolean isMillisecondResolution()
353 {
354 return m_millisecondResolution;
355 }
356
357 /**
358 * Gets the flag that indicates whether measurement timestamps use
359 * millisecond resolution. Otherwise, they will use 100-nanosecond
360 * resolution.
361 * <p>
362 * This flag determines the size of the timestamps transmitted as
363 * part of the compact measurement format when the server is using
364 * base time offsets.
365 *
366 * @param millisecondResolution the new value for the flag
367 * @see #isMillisecondResolution()
368 */
369 public void setMillisecondResolution(boolean millisecondResolution)
370 {
371 m_millisecondResolution = millisecondResolution;
372 }
373
374 /**
375 * Gets the start time of the requested temporal
376 * session for streaming historic data.
377 *
378 * @return the start time of the requested temporal session
379 * @see #setStartTime(String)
380 * @see #getStopTime()
381 * @see #getConstraintParameters()
382 */
383 public String getStartTime()
384 {
385 return m_startTime;
386 }
387
388 /**
389 * Sets the start time of the requested temporal
390 * session for streaming historic data.
391 *
392 * @param startTime the new value for the start time
393 * @see #getStartTime()
394 * @see #setStopTime(String)
395 * @see #setConstraintParameters(String)
396 */
397 public void setStartTime(String startTime)
398 {
399 m_startTime = startTime;
400 }
401
402 /**
403 * Gets the stop time of the requested temporal
404 * session for streaming historic data.
405 *
406 * @return the stop time of the requested temporal session
407 * @see #setStopTime(String)
408 * @see #getStartTime()
409 * @see #getConstraintParameters()
410 */
411 public String getStopTime()
412 {
413 return m_stopTime;
414 }
415
416 /**
417 * Sets the stop time of the requested temporal
418 * session for streaming historic data.
419 *
420 * @param stopTime the new value for the stop time
421 * @see #getStopTime()
422 * @see #setStartTime(String)
423 * @see #setConstraintParameters(String)
424 */
425 public void setStopTime(String stopTime)
426 {
427 m_stopTime = stopTime;
428 }
429
430 /**
431 * Gets the additional constraint parameters supplied
432 * to temporal adapters in a temporal session.
433 *
434 * @return the additional constraint parameters for temporal adapters
435 * @see #setConstraintParameters(String)
436 * @see #getStartTime()
437 * @see #getStopTime()
438 */
439 public String getConstraintParameters()
440 {
441 return m_constraintParameters;
442 }
443
444 /**
445 * Sets the additional constraint parameters supplied
446 * to temporal adapters in a temporal session.
447 *
448 * @param constraintParameters the new value for the additional parameters
449 * @see #getConstraintParameters()
450 * @see #setStartTime(String)
451 * @see #setStopTime(String)
452 */
453 public void setConstraintParameters(String constraintParameters)
454 {
455 m_constraintParameters = constraintParameters;
456 }
457
458 /**
459 * Gets the processing interval requested by the subscriber. A value
460 * of {@code -1} indicates the default processing interval. A value
461 * of {@code 0} indicates data will be processed as fast as possible.
462 *
463 * @return the processing interval requested by the subscriber
464 * @see #setProcessingInterval(int)
465 */
466 public int getProcessingInterval()
467 {
468 return m_processingInterval;
469 }
470
471 /**
472 * Sets the processing interval requested by the subscriber. A value
473 * of {@code -1} indicates the default processing interval. A value
474 * of {@code 0} indicates data will be processed as fast as possible.
475 *
476 * @param processingInterval the new value for the processing interval
477 * @see #getProcessingInterval()
478 */
479 public void setProcessingInterval(int processingInterval)
480 {
481 m_processingInterval = processingInterval;
482 }
483
484 /**
485 * Gets the wait handle names used to deterministically wait for data
486 * to become available on the server side.
487 *
488 * @return the wait handle names
489 * @see #setWaitHandleNames(String)
490 * @see #getWaitHandleTimeout()
491 */
492 public String getWaitHandleNames()
493 {
494 return m_waitHandleNames;
495 }
496
497 /**
498 * Sets the wait handle names used to deterministically wait for data
499 * to become available on the server side.
500 *
501 * @param waitHandleNames the new value for the wait handle names
502 * @see #getWaitHandleNames()
503 * @see #setWaitHandleTimeout(int)
504 */
505 public void setWaitHandleNames(String waitHandleNames)
506 {
507 m_waitHandleNames = waitHandleNames;
508 }
509
510 /**
511 * Gets the amount of time to wait on the wait handles identified by
512 * the wait handle names before the operation times out.
513 *
514 * @return the amount of time to wait on the wait handles before timing out
515 * @see #setWaitHandleTimeout(int)
516 * @see #getWaitHandleNames()
517 */
518 public int getWaitHandleTimeout()
519 {
520 return m_waitHandleTimeout;
521 }
522
523 /**
524 * Sets the amount of time to wait on the wait handle identified by
525 * the wait handle names before the operation times out.
526 *
527 * @param waitHandleTimeout the new value for the amount of time to
528 * wait on the wait handles before timing out
529 * @see #getWaitHandleTimeout()
530 * @see #setWaitHandleNames(String)
531 */
532 public void setWaitHandleTimeout(int waitHandleTimeout)
533 {
534 m_waitHandleTimeout = waitHandleTimeout;
535 }
536
537 /**
538 * Gets the additional connection string parameters to be applied
539 * to the connection string sent to the publisher during subscription.
540 *
541 * @return the additional connection string parameters sent to the
542 * publisher during subscription
543 * @see #setExtraConnectionStringParameters(String)
544 */
545 public String getExtraConnectionStringParameters()
546 {
547 return m_extraConnectionStringParameters;
548 }
549
550 /**
551 * Sets the additional connection string parameters to be applied
552 * to the connection string sent to the publisher during subscription.
553 *
554 * @param extraConnectionStringParameters the new value for the addtional
555 * connection string parameters sent to the publisher during
556 * subscription
557 * @see #getExtraConnectionStringParameters()
558 */
559 public void setExtraConnectionStringParameters(String extraConnectionStringParameters)
560 {
561 m_extraConnectionStringParameters = extraConnectionStringParameters;
562 }
563}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/CompressionMode.java+40−0
@@ -0,0 +1,40 @@
1//******************************************************************************************************
2// CompressionMode.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 09/14/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines character encodings supported by the Gateway Exchange Protocol.
28 */
29public class CompressionMode
30{
31 /**
32 * GZIP compression.
33 */
34 public static final int GZIP = 0x00000020;
35
36 /**
37 * No compression.
38 */
39 public static final int None = 0x00000000;
40}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/DataPacketFlags.java+52−0
@@ -0,0 +1,52 @@
1//******************************************************************************************************
2// DataPacketFlags.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines the flags used for compact measurement data packets.
28 */
29public class DataPacketFlags
30{
31 /**
32 * Attached to packets which are remotely synchronized.
33 */
34 public static final byte Synchronized = 0x01;
35
36 /**
37 * Attached to packets which are serialized
38 * using the compact measurement format.
39 */
40 public static final byte Compact = 0x02;
41
42 /**
43 * Indicates the index which identifies the cryptography
44 * key used to encrypt the data in the packet.
45 */
46 public static final byte CipherIndex = 0x03;
47
48 /**
49 * No flags.
50 */
51 public static final byte NoFlags = 0x00;
52}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/OperationalEncoding.java+54−0
@@ -0,0 +1,54 @@
1//******************************************************************************************************
2// OperationalEncoding.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines character encodings supported by the Gateway Exchange Protocol.
28 */
29public class OperationalEncoding
30{
31 /**
32 * Little-endian UTF-16.
33 */
34 public static final int Unicode = 0x00000000;
35
36 /**
37 * Big-endian UTF-16.
38 */
39 public static final int BigEndianUnicode = 0x00000100;
40
41 /**
42 * UTF-8
43 */
44 public static final int UTF8 = 0x00000200;
45
46 /**
47 * The default character encoding used by the operating system.
48 * This option may not work properly if the two systems that
49 * are communicating are not using the same operating system default.
50 * On Windows systems, this will often be compatible with the ANSI
51 * option defined in the C# implementation of the Publisher API.
52 */
53 public static final int OperatingSystemDefault = 0x00000300;
54}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/OperationalModes.java+78−0
@@ -0,0 +1,78 @@
1//******************************************************************************************************
2// OperationalModes.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines flags and bitmasks used in the operational modes
28 * that define how the subscriber and publisher communicate.
29 * Operational modes are the first things that get transmitted
30 * to the publisher after a successful connection.
31 */
32public class OperationalModes
33{
34 /**
35 * Bitmask to extract the protocol version from the operational modes.
36 */
37 public static final int VersionMask = 0x0000001F;
38
39 /**
40 * Bitmask to extract the compression mode from the operational modes.
41 * Compression is currently not supported; these bits are reserved.
42 */
43 public static final int CompressionModeMask = 0x000000E0;
44
45 /**
46 * Bitmask to extract the operational encoding from the operational modes.
47 *
48 * @see OperationalEncoding
49 */
50 public static final int EncodingMask = 0x00000300;
51
52 /**
53 * Flag that determines whether to use the common serialization format.
54 * If the bit is set, the common serialization format is used. If the
55 * flag is unset, the .NET serialization format is used. This Java
56 * implementation of the Subscriber API only supports the common
57 * serialization format.
58 */
59 public static final int UseCommonSerializationFormat = 0x01000000;
60
61 /**
62 * Flag that determines whether to compress the signal index cache.
63 * This Java implementation of the Subscriber API does not yet support
64 * compression of the signal index cache.
65 */
66 public static final int CompressSignalIndexCache = 0x40000000;
67
68 /**
69 * Flag that determines whether to compress the metadata transmitted
70 * from the publisher to the subscriber.
71 */
72 public static final int CompressMetadata = 0x80000000;
73
74 /**
75 * No flags.
76 */
77 public static final int NoFlags = 0x00000000;
78}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/ServerCommand.java+82−0
@@ -0,0 +1,82 @@
1//******************************************************************************************************
2// ServerCommand.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines command codes for the commands that can
28 * be sent to the publisher via the command channel.
29 */
30public class ServerCommand
31{
32 /**
33 * Indicates that the subscriber would like to authenticate.
34 * <p>
35 * The data that accompanies this message is the encrypted
36 * authentication string prefixed with its byte length. The
37 * byte length should be unencrypted. The authentication
38 * string consists of the subscriber's authentication ID
39 * prefixed with a random, 8-byte salt.
40 */
41 public static final byte Authenticate = 0x00;
42
43 /**
44 * Indicates that the subscriber would like
45 * to receive metadata from the publisher.
46 */
47 public static final byte MetadataRefresh = 0x01;
48
49 /**
50 * Indicates that the subscriber would like
51 * to receive measurements from the publisher.
52 * <p>
53 * The data that accompanies this message is the connection string
54 * which defines several configuration options that can be asked
55 * of the publisher.
56 */
57 public static final byte Subscribe = 0x02;
58
59 /**
60 * Indicates that the subscriber would like to stop
61 * receiving measurements from the publisher.
62 */
63 public static final byte Unsubscribe = 0x03;
64
65 /**
66 * Indicates that the subscriber would
67 * like to initiate a cipher key rotation.
68 */
69 public static final byte RotateCipherKeys = 0x04;
70
71 /**
72 * Indicates that the subscriber would like
73 * to change its measurement processing interval.
74 */
75 public static final byte UpdateProcessingInterval = 0x05;
76
77 /**
78 * Indicates that the subscriber would like to define
79 * or change the way it is communicating with the publisher.
80 */
81 public static final byte DefineOperationalModes = 0x06;
82}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/constant/ServerResponse.java+86−0
@@ -0,0 +1,86 @@
1//******************************************************************************************************
2// ServerResponse.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.constant;
25
26/**
27 * Defines response codes that can be sent by the publisher back to the
28 * subscriber.
29 */
30public class ServerResponse
31{
32 /**
33 * Indicates that a command sent by the subscriber has been successfully
34 * processed and handled.
35 */
36 public static final byte Succeeded = (byte) 0x80;
37
38 /**
39 * Indicates that the publisher was unable to properly process and handle a
40 * command sent by the publisher.
41 */
42 public static final byte Failed = (byte) 0x81;
43
44 /**
45 * Indicates that the packet sent with this code contains measurement data.
46 */
47 public static final byte DataPacket = (byte) 0x82;
48
49 /**
50 * Indicates that the packet sent with this code contains the serialized
51 * signal index cache.
52 */
53 public static final byte UpdateSignalIndexCache = (byte) 0x83;
54
55 /**
56 * Indicates that the packet sent with this code contains the serialized
57 * base time offsets.
58 */
59 public static final byte UpdateBaseTimes = (byte) 0x84;
60
61 /**
62 * Indicates that the packet sent with this code contains the cipher keys
63 * used for encryption.
64 */
65 public static final byte UpdateCipherKeys = (byte) 0x85;
66
67 /**
68 * Indicates that the publisher has started sending measurement data, and
69 * the message includes the server's local time taken when the data stream
70 * was started.
71 */
72 public static final byte DataStartTime = (byte) 0x86;
73
74 /**
75 * Indicates that a temporal session has been completed.
76 */
77 public static final byte ProcessingComplete = (byte) 0x87;
78
79 /**
80 * Indicates that no action should be taken by the subscriber.
81 * This message is sent periodically by the publisher over the
82 * command channel in order to verify that the connection is
83 * still open.
84 */
85 public static final byte NoOP = (byte) 0xFF;
86}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MeasurementEvent.java+66−0
@@ -0,0 +1,66 @@
1//******************************************************************************************************
2// MeasurementEvent.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import java.util.Collection;
27import java.util.Collections;
28import java.util.EventObject;
29
30import org.gpa.tsf.Measurement;
31
32/**
33 * Event that occurs when new measurements are received from the publisher.
34 */
35public class MeasurementEvent extends EventObject
36{
37 private Collection<Measurement> m_measurements;
38
39 /**
40 * Constructs a new instance.
41 *
42 * @param source the source of the event
43 * @param measurements the new measurements received from the publisher
44 */
45 public MeasurementEvent(Object source, Collection<Measurement> measurements)
46 {
47 super(source);
48
49 if (measurements == null)
50 throw new IllegalArgumentException("measurements cannot be null");
51
52 m_measurements = Collections.unmodifiableCollection(measurements);
53 }
54
55 /**
56 * Gets the measurements that were received from the publisher.
57 *
58 * @return the measurements received from the publisher
59 */
60 public Collection<Measurement> getMeasurements()
61 {
62 return m_measurements;
63 }
64
65 private static final long serialVersionUID = 5788181880673812873L;
66}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MessageEvent.java+86−0
@@ -0,0 +1,86 @@
1//******************************************************************************************************
2// MessageEvent.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import java.util.EventObject;
27
28/**
29 * Event that occurs when the subscriber
30 * needs to expose a message to the user.
31 */
32public class MessageEvent extends EventObject
33{
34 private String m_message;
35 private Exception m_exception;
36
37 /**
38 * Constructs a new instance.
39 *
40 * @param source the source of the message
41 * @param message the message to be exposed
42 */
43 public MessageEvent(Object source, String message)
44 {
45 super(source);
46 m_message = message;
47 }
48
49 /**
50 * Constructs a new instance associated with an exception.
51 *
52 * @param source the source of the exception
53 * @param exception the exception to be exposed
54 */
55 public MessageEvent(Object source, Exception exception)
56 {
57 this(source, exception.getMessage());
58 m_exception = exception;
59 }
60
61 /**
62 * Gets the message to be exposed to the user. If this
63 * {@code MessageEvent} is associated with an exception,
64 * this is equivalent to calling {@code getException().getMessage()}.
65 *
66 * @return the message to be exposed to the user
67 */
68 public String getMessage()
69 {
70 return m_message;
71 }
72
73 /**
74 * Gets the exception associated with this
75 * message event, or null if there is none.
76 *
77 * @return the exception associated with the message event,
78 * if there is one
79 */
80 public Exception getException()
81 {
82 return m_exception;
83 }
84
85 private static final long serialVersionUID = -6228918892670504322L;
86}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/MetadataEvent.java+91−0
@@ -0,0 +1,91 @@
1//******************************************************************************************************
2// MetadataEvent.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import java.util.EventObject;
27
28/**
29 * Event that occurs when the subscriber receives metadata from the publisher.
30 */
31public class MetadataEvent extends EventObject
32{
33 private byte[] m_compressedMetadata;
34 private String m_xmlMetadata;
35
36 /**
37 * Constructs a new instance.
38 *
39 * @param source the source of the event
40 * @param compressedMetadata the compressed metadata
41 */
42 public MetadataEvent(Object source, byte[] compressedMetadata)
43 {
44 super(source);
45
46 if (compressedMetadata == null)
47 throw new IllegalArgumentException("compressedMetadata cannot be null");
48
49 m_compressedMetadata = compressedMetadata;
50 }
51
52 /**
53 * Constructs a new instance.
54 *
55 * @param source the source of the event
56 * @param xmlMetadata the uncompressed metadata
57 */
58 public MetadataEvent(Object source, String xmlMetadata)
59 {
60 super(source);
61
62 if (xmlMetadata == null)
63 throw new IllegalArgumentException("xmlMetadata cannot be null");
64
65 m_xmlMetadata = xmlMetadata;
66 }
67
68 /**
69 * Gets the compressed metadata received from the publisher.
70 * If the metadata received was uncompressed, this will return null.
71 *
72 * @return byte array containing the compressed metadata
73 */
74 public byte[] getCompressedMetadata()
75 {
76 return m_compressedMetadata;
77 }
78
79 /**
80 * Gets the uncompressed metadata received from the publisher.
81 * If the metadata received was compressed, this will return null.
82 *
83 * @return the uncompressed XML metadata
84 */
85 public String getXmlMetadata()
86 {
87 return m_xmlMetadata;
88 }
89
90 private static final long serialVersionUID = -1703909541078304245L;
91}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/StartTimeEvent.java+59−0
@@ -0,0 +1,59 @@
1//******************************************************************************************************
2// SubscriberEvent.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import java.util.EventObject;
27
28/**
29 * Event that occurs when the subscriber receives
30 * the data start time from the publisher.
31 */
32public class StartTimeEvent extends EventObject
33{
34 private long m_dataStartTime;
35
36 /**
37 * Constructs a new instance with the given data start time.
38 *
39 * @param source the source of the event
40 * @param dataStartTime the data start time received from the publisher
41 */
42 public StartTimeEvent(Object source, long dataStartTime)
43 {
44 super(source);
45 m_dataStartTime = dataStartTime;
46 }
47
48 /**
49 * Gets the data start time received from the publisher.
50 *
51 * @return the data start time
52 */
53 public long getDataStartTime()
54 {
55 return m_dataStartTime;
56 }
57
58 private static final long serialVersionUID = -3551015702900244809L;
59}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberAdapter.java+69−0
@@ -0,0 +1,69 @@
1//******************************************************************************************************
2// SubscriberAdapter.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26/**
27 * An abstract adapter class for receiving subscriber events. The
28 * methods in this class are empty. This class exists as convenience
29 * for creating listener objects.
30 */
31public class SubscriberAdapter implements SubscriberListener
32{
33
34 @Override
35 public void statusMessageReceived(MessageEvent evt)
36 {
37 }
38
39 @Override
40 public void exceptionEncountered(MessageEvent evt)
41 {
42 }
43
44 @Override
45 public void dataStartTimeReceived(StartTimeEvent evt)
46 {
47 }
48
49 @Override
50 public void metadataReceived(MetadataEvent evt)
51 {
52 }
53
54 @Override
55 public void newMeasurementsReceived(MeasurementEvent evt)
56 {
57 }
58
59 @Override
60 public void processingCompleteCallback(MessageEvent evt)
61 {
62 }
63
64 @Override
65 public void connectionTerminated(MessageEvent evt)
66 {
67 }
68
69}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberConnectorAdapter.java+44−0
@@ -0,0 +1,44 @@
1//******************************************************************************************************
2// SubscriberConnectorAdapter.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26/**
27 * An abstract adapter class for receiving subscriber connector events.
28 * The methods in this class are empty. This class exists as convenience
29 * for creating listener objects.
30 */
31public class SubscriberConnectorAdapter implements SubscriberConnectorListener
32{
33
34 @Override
35 public void exceptionEncountered(MessageEvent evt)
36 {
37 }
38
39 @Override
40 public void reconnected(SubscriberEvent evt)
41 {
42 }
43
44}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberConnectorListener.java+47−0
@@ -0,0 +1,47 @@
1//******************************************************************************************************
2// SubscriberConnectorListener.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26/**
27 * Interface which defines callbacks for the {@link SubscriberConnector}.
28 */
29public interface SubscriberConnectorListener
30{
31 /**
32 * Called when an exception is encountered
33 * by the {@code SubscriberConnector}.
34 *
35 * @param evt the event which contains the exception
36 */
37 void exceptionEncountered(MessageEvent evt);
38
39 /**
40 * Occurs when the subscriber is automatically
41 * reconnected by the {@code SubscriberConnector}.
42 *
43 * @param evt the event which contains the subscriber
44 * that was reconnected
45 */
46 void reconnected(SubscriberEvent evt);
47}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberEvent.java+60−0
@@ -0,0 +1,60 @@
1//******************************************************************************************************
2// SubscriberEvent.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import java.util.EventObject;
27
28import org.gpa.tsf.transport.DataSubscriber;
29
30/**
31 * Generic event associated with a subscriber.
32 */
33public class SubscriberEvent extends EventObject
34{
35 private DataSubscriber m_subscriber;
36
37 /**
38 * Constructs a new instance.
39 *
40 * @param source the source of the event
41 * @param subscriber the subscriber associated with the event
42 */
43 public SubscriberEvent(Object source, DataSubscriber subscriber)
44 {
45 super(source);
46 m_subscriber = subscriber;
47 }
48
49 /**
50 * Gets the subscriber associated with the event.
51 *
52 * @return the subscriber associated with the event
53 */
54 public DataSubscriber getSubscriber()
55 {
56 return m_subscriber;
57 }
58
59 private static final long serialVersionUID = -1854428244027543102L;
60}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/transport/event/SubscriberListener.java+90−0
@@ -0,0 +1,90 @@
1//******************************************************************************************************
2// SubscriberListener.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.transport.event;
25
26import org.gpa.tsf.transport.DataSubscriber;
27
28/**
29 * Interface which defines the callbacks
30 * used by the subscriber to handle events.
31 *
32 * @see DataSubscriber
33 * @see DataSubscriber#addSubscriberListener(SubscriberListener)
34 */
35public interface SubscriberListener
36{
37 /**
38 * Occurs when the subscriber wishes to
39 * expose a status message to the user.
40 *
41 * @param evt the message event which contains the status message
42 */
43 void statusMessageReceived(MessageEvent evt);
44
45 /**
46 * Occurs when the subscriber encounters an exception.
47 *
48 * @param evt the message event which contains the exception encountered
49 */
50 void exceptionEncountered(MessageEvent evt);
51
52 /**
53 * Occurs when the data start time is received from the publisher.
54 *
55 * @param evt the event which contains the data start time received
56 */
57 void dataStartTimeReceived(StartTimeEvent evt);
58
59 /**
60 * Occurs when metadata is received from the publisher.
61 *
62 * @param evt the metadata event which contains the metadata received
63 */
64 void metadataReceived(MetadataEvent evt);
65
66 /**
67 * Occurs when a new collection of measurements
68 * are received from the publisher.
69 *
70 * @param evt the collection of measurements received
71 */
72 void newMeasurementsReceived(MeasurementEvent evt);
73
74 /**
75 * Occurs when the publisher notifies the subscriber
76 * that a temporal session has been completed.
77 *
78 * @param evt the event which contains a message from the publisher
79 */
80 void processingCompleteCallback(MessageEvent evt);
81
82 /**
83 * Occurs when the TCP connection between the publisher
84 * and subscriber is terminated unexpectedly.
85 *
86 * @param evt the event which contains an exception that occurred as
87 * a result of the connection termination
88 */
89 void connectionTerminated(MessageEvent evt);
90}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/ArrayExtensions.java+195−0
@@ -0,0 +1,195 @@
1//******************************************************************************************************
2// ArrayExtensions.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/18/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26/**
27 * Utility class that provides additional functionality for arrays.
28 */
29public class ArrayExtensions
30{
31 /**
32 * Copies the specified number of bytes from the source array to the
33 * destination array, starting from the given offsets in each array.
34 *
35 * @param source the source array
36 * @param srcOffset the offset into the source array where the data
37 * to be copied starts
38 * @param dest the destination array
39 * @param destOffset the offset into the destination array where the
40 * data is to be copied
41 * @param length the amount of data to be copied
42 */
43 public static void blockCopy(byte[] source, int srcOffset, byte[] dest, int destOffset, int length)
44 {
45 for (int i = 0; i < length; i++)
46 dest[destOffset + i] = source[srcOffset + i];
47 }
48
49 /**
50 * Copies the specified number of short integers from the source array
51 * to the destination array, starting from the given offsets in each
52 * array.
53 *
54 * @param source the source array
55 * @param srcOffset the offset into the source array where the data
56 * to be copied starts
57 * @param dest the destination array
58 * @param destOffset the offset into the destination array where the
59 * data is to be copied
60 * @param length the amount of data to be copied
61 */
62 public static void blockCopy(short[] source, int srcOffset, short[] dest, int destOffset, int length)
63 {
64 for (int i = 0; i < length; i++)
65 dest[destOffset + i] = source[srcOffset + i];
66 }
67
68 /**
69 * Copies the specified number of integers from the source array to the
70 * destination array, starting from the given offsets in each array.
71 *
72 * @param source the source array
73 * @param srcOffset the offset into the source array where the data
74 * to be copied starts
75 * @param dest the destination array
76 * @param destOffset the offset into the destination array where the
77 * data is to be copied
78 * @param length the amount of data to be copied
79 */
80 public static void blockCopy(int[] source, int srcOffset, int[] dest, int destOffset, int length)
81 {
82 for (int i = 0; i < length; i++)
83 dest[destOffset + i] = source[srcOffset + i];
84 }
85
86 /**
87 * Copies the specified number of long integers from the source array
88 * to the destination array, starting from the given offsets in each
89 * array.
90 *
91 * @param source the source array
92 * @param srcOffset the offset into the source array where the data
93 * to be copied starts
94 * @param dest the destination array
95 * @param destOffset the offset into the destination array where the
96 * data is to be copied
97 * @param length the amount of data to be copied
98 */
99 public static void blockCopy(long[] source, int srcOffset, long[] dest, int destOffset, int length)
100 {
101 for (int i = 0; i < length; i++)
102 dest[destOffset + i] = source[srcOffset + i];
103 }
104
105 /**
106 * Copies the specified number of floats from the source array to the
107 * destination array, starting from the given offsets in each array.
108 *
109 * @param source the source array
110 * @param srcOffset the offset into the source array where the data
111 * to be copied starts
112 * @param dest the destination array
113 * @param destOffset the offset into the destination array where the
114 * data is to be copied
115 * @param length the amount of data to be copied
116 */
117 public static void blockCopy(float[] source, int srcOffset, float[] dest, int destOffset, int length)
118 {
119 for (int i = 0; i < length; i++)
120 dest[destOffset + i] = source[srcOffset + i];
121 }
122
123 /**
124 * Copies the specified number of doubles from the source array to the
125 * destination array, starting from the given offsets in each array.
126 *
127 * @param source the source array
128 * @param srcOffset the offset into the source array where the data
129 * to be copied starts
130 * @param dest the destination array
131 * @param destOffset the offset into the destination array where the
132 * data is to be copied
133 * @param length the amount of data to be copied
134 */
135 public static void blockCopy(double[] source, int srcOffset, double[] dest, int destOffset, int length)
136 {
137 for (int i = 0; i < length; i++)
138 dest[destOffset + i] = source[srcOffset + i];
139 }
140
141 /**
142 * Copies the specified number of boolean values from the source array
143 * to the destination array, starting from the given offsets in each
144 * array.
145 *
146 * @param source the source array
147 * @param srcOffset the offset into the source array where the data
148 * to be copied starts
149 * @param dest the destination array
150 * @param destOffset the offset into the destination array where the
151 * data is to be copied
152 * @param length the amount of data to be copied
153 */
154 public static void blockCopy(boolean[] source, int srcOffset, boolean[] dest, int destOffset, int length)
155 {
156 for (int i = 0; i < length; i++)
157 dest[destOffset + i] = source[srcOffset + i];
158 }
159
160 /**
161 * Copies the specified number of characters from the source array to the
162 * destination array, starting from the given offsets in each array.
163 *
164 * @param source the source array
165 * @param srcOffset the offset into the source array where the data
166 * to be copied starts
167 * @param dest the destination array
168 * @param destOffset the offset into the destination array where the
169 * data is to be copied
170 * @param length the amount of data to be copied
171 */
172 public static void blockCopy(char[] source, int srcOffset, char[] dest, int destOffset, int length)
173 {
174 for (int i = 0; i < length; i++)
175 dest[destOffset + i] = source[srcOffset + i];
176 }
177
178 /**
179 * Copies the specified number of objects from the source array to the
180 * destination array, starting from the given offsets in each array.
181 *
182 * @param source the source array
183 * @param srcOffset the offset into the source array where the data
184 * to be copied starts
185 * @param dest the destination array
186 * @param destOffset the offset into the destination array where the
187 * data is to be copied
188 * @param length the amount of data to be copied
189 */
190 public static <T> void blockCopy(T[] source, int srcOffset, T[] dest, int destOffset, int length)
191 {
192 for (int i = 0; i < length; i++)
193 dest[destOffset + i] = source[srcOffset + i];
194 }
195}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/InputStreamExtensions.java+73−0
@@ -0,0 +1,73 @@
1//******************************************************************************************************
2// InputStreamExtensions.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/16/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26import java.io.BufferedInputStream;
27import java.io.IOException;
28import java.io.InputStream;
29
30/**
31 * Utility class that provides additional functionality for input streams.
32 *
33 * @author Stephen C. Wills
34 */
35public class InputStreamExtensions
36{
37 /**
38 * This read method works approximately the same as the
39 * {@link BufferedInputStream#read(byte[], int, int)} method.
40 * The main difference is that this method will block until the
41 * requested amount of data is read from the input stream or the
42 * end of the stream has been reached, whereas BufferedInputStream
43 * will try to avoid blocking by checking the {@code available()}
44 * method of the underlying stream.
45 *
46 * @param stream source of the data
47 * @param buffer destination buffer
48 * @param offset offset at which to start storing bytes
49 * @param length requested number of bytes
50 * @return the number of bytes read from the stream, or -1 if the end of the stream has been reached
51 * @throws IOException if this input stream has been closed by invoking its
52 * {@link InputStream#close()} method, or an I/O error occurs
53 * @see java.io.BufferedInputStream
54 */
55 public static int read(InputStream stream, byte[] buffer, int offset, int length) throws IOException
56 {
57 int index = offset;
58 int readAmount = 0;
59 int totalReadAmount = 0;
60
61 while (readAmount >= 0 && totalReadAmount < length)
62 {
63 readAmount = stream.read(buffer, index, length - readAmount);
64 index += readAmount;
65 totalReadAmount += readAmount;
66 }
67
68 if (readAmount < 0 && totalReadAmount == 0)
69 totalReadAmount = -1;
70
71 return totalReadAmount;
72 }
73}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/Masks.java+92−0
@@ -0,0 +1,92 @@
1//******************************************************************************************************
2// Masks.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26/**
27 * Utility class to properly generate masks for different sizes of integers.
28 *
29 * @author Stephen C. Wills
30 */
31public class Masks
32{
33 /**
34 * Gets a 64-bit integer mask with the given
35 * number of least significant bits turned on.
36 *
37 * @param numberOfOnBits The number of bits to be turned on.
38 * @return a 64-bit integer mask
39 */
40 public static long getLongMask(int numberOfOnBits)
41 {
42 if(numberOfOnBits < 0 || numberOfOnBits > Long.SIZE)
43 throw new IllegalArgumentException("Number of masked bits must be between 0 and " + Long.SIZE);
44
45 return ~(~0L << numberOfOnBits);
46 }
47
48 /**
49 * Gets a 32-bit integer mask with the given
50 * number of least significant bits turned on.
51 *
52 * @param numberOfOnBits The number of bits to be turned on.
53 * @return a 32-bit integer mask
54 */
55 public static int getIntMask(int numberOfOnBits)
56 {
57 if(numberOfOnBits < 0 || numberOfOnBits > Integer.SIZE)
58 throw new IllegalArgumentException("Number of masked bits must be between 0 and " + Integer.SIZE);
59
60 return ~(~0 << numberOfOnBits);
61 }
62
63 /**
64 * Gets a 16-bit integer mask with the given
65 * number of least significant bits turned on.
66 *
67 * @param numberOfOnBits The number of bits to be turned on.
68 * @return a 16-bit integer mask
69 */
70 public static short getShortMask(int numberOfOnBits)
71 {
72 if(numberOfOnBits < 0 || numberOfOnBits > Short.SIZE)
73 throw new IllegalArgumentException("Number of masked bits must be between 0 and " + Short.SIZE);
74
75 return (short)getIntMask(numberOfOnBits);
76 }
77
78 /**
79 * Gets a 8-bit integer mask with the given
80 * number of least significant bits turned on.
81 *
82 * @param numberOfOnBits The number of bits to be turned on.
83 * @return a 8-bit integer mask
84 */
85 public static byte getByteMask(int numberOfOnBits)
86 {
87 if(numberOfOnBits < 0 || numberOfOnBits > Byte.SIZE)
88 throw new IllegalArgumentException("Number of masked bits must be between 0 and " + Byte.SIZE);
89
90 return (byte)getIntMask(numberOfOnBits);
91 }
92}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/NumberExtensions.java+132−0
@@ -0,0 +1,132 @@
1//******************************************************************************************************
2// NumberExtensions.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/12/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26import java.math.BigInteger;
27
28/**
29 * Utility class that provides additional functionality for numbers.
30 *
31 * @author Stephen C. Wills
32 */
33public class NumberExtensions
34{
35 /**
36 * Gets a string representation of a long integer
37 * in base 10 as if it were an unsigned long integer.
38 *
39 * @param num the long integer to be converted to a string
40 * @return a string representation of the given long integer
41 * @see Long#toString(long)
42 */
43 public static String toUnsignedString(long num)
44 {
45 return toUnsignedString(num, 10);
46 }
47
48 /**
49 * Gets a string representation of a long integer
50 * as if it were an unsigned long integer.
51 *
52 * @param num the long integer to be converted to a string
53 * @param radix the radix to use in the string representation
54 * @return a string representation of the given long integer
55 * @see Long#toString(long, int)
56 */
57 public static String toUnsignedString(long num, int radix)
58 {
59 BigInteger bigNum;
60 BigInteger bigMod;
61
62 if (num > 0L)
63 return Long.toString(radix);
64
65 bigNum = BigInteger.valueOf(num >>> 1);
66 bigMod = BigInteger.valueOf(num & 1L);
67
68 return bigNum.shiftLeft(1).add(bigMod).toString(radix);
69 }
70
71 /**
72 * Gets a string representation of an integer in
73 * base 10 as if it were an unsigned integer.
74 *
75 * @param num the integer to be converted to a string
76 * @return a string representation of the given integer
77 * @see Integer#toString(int)
78 */
79 public static String toUnsignedString(int num)
80 {
81 return toUnsignedString(num, 10);
82 }
83
84 /**
85 * Gets a string representation of an integer
86 * as if it were an unsigned integer.
87 *
88 * @param num the integer to be converted to a string
89 * @param radix the radix to use in the string representation
90 * @return a string representation of the given integer
91 * @see Integer#toString(int, int)
92 */
93 public static String toUnsignedString(int num, int radix)
94 {
95 if (num > 0)
96 return Integer.toString(num, radix);
97
98 return Long.toString(num & Masks.getLongMask(Integer.SIZE), radix);
99 }
100
101 /**
102 * Gets a string representation of a short integer
103 * in base 10 as if it were an unsigned short integer.
104 *
105 * @param num the short integer to be converted to a string
106 * @return a string representation of the given short integer
107 * @see Short#toString(short)
108 */
109 public static String toUnsignedString(short num)
110 {
111 if (num > 0)
112 return Short.toString(num);
113
114 return Integer.toString(num & Masks.getIntMask(Short.SIZE));
115 }
116
117 /**
118 * Gets a string representation of a byte in
119 * base 10 as if it were an unsigned byte.
120 *
121 * @param num the byte to be converted to a string
122 * @return a string representation of the given byte
123 * @see Byte#toString(byte)
124 */
125 public static String toUnsignedString(byte num)
126 {
127 if (num > 0)
128 return Byte.toString(num);
129
130 return Integer.toString(num & Masks.getIntMask(Byte.SIZE));
131 }
132}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/StringExtensions.java+88−0
@@ -0,0 +1,88 @@
1//******************************************************************************************************
2// StringExtensions.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/18/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26/**
27 * Utility class that provides additional functionality for strings.
28 */
29public class StringExtensions
30{
31 /**
32 * Determines whether the given string is null or the empty string.
33 *
34 * @param str the string to be checked
35 * @return true if the string is null or empty; false otherwise
36 */
37 public static boolean isNullOrEmpty(String str)
38 {
39 return (str == null) || str.isEmpty();
40 }
41
42 /**
43 * Determines whether the given string is null or contains
44 * nothing but whitespace characters.
45 *
46 * @param str the string to be checked
47 * @return true if the string is null or whitespace; false otherwise
48 */
49 public static boolean isNullOrWhitespace(String str)
50 {
51 return (str == null) || str.trim().isEmpty();
52 }
53
54 /**
55 * Converts null strings to the empty string. If a string is provided
56 * which is not null, no operation is performed and the string is
57 * returned as-is.
58 *
59 * @param str the string to be checked
60 * @return the empty string if the parameter is null; otherwise the
61 * parameter itself is returned
62 */
63 public static String toNonNull(String str)
64 {
65 return toNonNull(str, "");
66 }
67
68 /**
69 * Converts null strings to the given default string value. If a
70 * string is provided which is not null, no operation is performed
71 * and the string is returned as-is.
72 *
73 * @param str the string to be checked
74 * @param defaultValue the default value to return if the provided
75 * string happens to be null
76 * @return the default value if the first parameter is null; otherwise
77 * the first parameter itself is returned
78 */
79 public static String toNonNull(String str, String defaultValue)
80 {
81 if (str != null)
82 return str;
83 else if (defaultValue != null)
84 return defaultValue;
85 else
86 return "";
87 }
88}
Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/util/TimeExtensions.java+65−0
@@ -0,0 +1,65 @@
1//******************************************************************************************************
2// TimeExtensions.java - Gbtc
3//
4// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9// not use this file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://www.opensource.org/licenses/eclipse-1.0.php
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/23/2012 - Stephen C. Wills
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24package org.gpa.tsf.util;
25
26import java.util.Calendar;
27
28/**
29 * Utility class which provides additional
30 * functionality for time representations.
31 */
32public class TimeExtensions
33{
34 /**
35 * Converts a value in ticks (100-nanosecond intervals since midnight,
36 * January 1, 0001) into a {@link Calendar} instance. Some loss of
37 * precision is incurred as {@code Calendar}s store up to millisecond
38 * precision.
39 *
40 * @param ticks the value in ticks to be converted
41 * @return the equivalent {@code Calendar} instance
42 * @see #toTicks(Calendar)
43 */
44 public static Calendar fromTicks(long ticks)
45 {
46 Calendar calendar = Calendar.getInstance();
47 calendar.setTimeInMillis((ticks - TicksAtEpoch) / TicksPerMillisecond);
48 return calendar;
49 }
50
51 /**
52 * Converts a {@link Calendar} instance into a value in ticks.
53 *
54 * @param calendar the {@code Calendar} instance to be converted
55 * @return the equivalent value in ticks
56 * @see #fromTicks(long)
57 */
58 public static long toTicks(Calendar calendar)
59 {
60 return (calendar.getTimeInMillis() * TicksPerMillisecond) + TicksAtEpoch;
61 }
62
63 private static final long TicksAtEpoch = 621355968000000000L;
64 private static final long TicksPerMillisecond = 10000L;
65}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t