001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.catalina.tribes.demos;
018:
019: import java.io.Serializable;
020: import java.util.Map;
021:
022: import java.awt.ComponentOrientation;
023: import java.awt.Dimension;
024: import java.awt.event.ActionEvent;
025: import java.awt.event.ActionListener;
026: import java.awt.event.MouseAdapter;
027: import java.awt.event.MouseEvent;
028: import javax.swing.BoxLayout;
029: import javax.swing.JButton;
030: import javax.swing.JFrame;
031: import javax.swing.JPanel;
032: import javax.swing.JScrollPane;
033: import javax.swing.JTable;
034: import javax.swing.JTextField;
035: import javax.swing.table.AbstractTableModel;
036: import javax.swing.table.TableModel;
037:
038: import org.apache.catalina.tribes.Channel;
039: import org.apache.catalina.tribes.ChannelListener;
040: import org.apache.catalina.tribes.ManagedChannel;
041: import org.apache.catalina.tribes.Member;
042: import org.apache.catalina.tribes.MembershipListener;
043: import org.apache.catalina.tribes.tipis.AbstractReplicatedMap;
044: import org.apache.catalina.tribes.tipis.LazyReplicatedMap;
045: import javax.swing.table.DefaultTableCellRenderer;
046: import java.awt.Color;
047: import java.awt.Component;
048: import javax.swing.table.TableColumn;
049: import org.apache.catalina.tribes.util.UUIDGenerator;
050: import org.apache.catalina.tribes.util.Arrays;
051: import java.util.Set;
052:
053: /**
054: * <p>Title: </p>
055: *
056: * <p>Description: </p>
057: *
058: * <p>Company: </p>
059: *
060: * @author not attributable
061: * @version 1.0
062: */
063: public class MapDemo implements ChannelListener, MembershipListener {
064:
065: protected LazyReplicatedMap map;
066: protected SimpleTableDemo table;
067:
068: public MapDemo(Channel channel, String mapName) {
069: map = new LazyReplicatedMap(null, channel, 5000, mapName, null);
070: table = SimpleTableDemo.createAndShowGUI(map, channel
071: .getLocalMember(false).getName());
072: channel.addChannelListener(this );
073: channel.addMembershipListener(this );
074: // for ( int i=0; i<1000; i++ ) {
075: // map.put("MyKey-"+i,"My String Value-"+i);
076: // }
077: this .messageReceived(null, null);
078: }
079:
080: public boolean accept(Serializable msg, Member source) {
081: table.dataModel.getValueAt(-1, -1);
082: return false;
083: }
084:
085: public void messageReceived(Serializable msg, Member source) {
086:
087: }
088:
089: public void memberAdded(Member member) {
090: }
091:
092: public void memberDisappeared(Member member) {
093: table.dataModel.getValueAt(-1, -1);
094: }
095:
096: public static void usage() {
097: System.out.println("Tribes MapDemo.");
098: System.out.println("Usage:\n\t"
099: + "java MapDemo [channel options] mapName\n\t"
100: + "\tChannel options:" + ChannelCreator.usage());
101: }
102:
103: public static void main(String[] args) throws Exception {
104: long start = System.currentTimeMillis();
105: ManagedChannel channel = (ManagedChannel) ChannelCreator
106: .createChannel(args);
107: String mapName = "MapDemo";
108: if (args.length > 0 && (!args[args.length - 1].startsWith("-"))) {
109: mapName = args[args.length - 1];
110: }
111: channel.start(channel.DEFAULT);
112: Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
113: MapDemo demo = new MapDemo(channel, mapName);
114:
115: System.out.println("System test complete, time to start="
116: + (System.currentTimeMillis() - start)
117: + " ms. Sleeping to let threads finish.");
118: Thread.sleep(60 * 1000 * 60);
119: }
120:
121: public static class Shutdown extends Thread {
122: ManagedChannel channel = null;
123:
124: public Shutdown(ManagedChannel channel) {
125: this .channel = channel;
126: }
127:
128: public void run() {
129: System.out.println("Shutting down...");
130: SystemExit exit = new SystemExit(5000);
131: exit.setDaemon(true);
132: exit.start();
133: try {
134: channel.stop(channel.DEFAULT);
135:
136: } catch (Exception x) {
137: x.printStackTrace();
138: }
139: System.out.println("Channel stopped.");
140: }
141: }
142:
143: public static class SystemExit extends Thread {
144: private long delay;
145:
146: public SystemExit(long delay) {
147: this .delay = delay;
148: }
149:
150: public void run() {
151: try {
152: Thread.sleep(delay);
153: } catch (Exception x) {
154: x.printStackTrace();
155: }
156: System.exit(0);
157:
158: }
159: }
160:
161: public static class SimpleTableDemo extends JPanel implements
162: ActionListener {
163: private static int WIDTH = 550;
164:
165: private LazyReplicatedMap map;
166: private boolean DEBUG = false;
167: AbstractTableModel dataModel = new AbstractTableModel() {
168:
169: String[] columnNames = { "Key", "Value", "Backup Node",
170: "isPrimary", "isProxy", "isBackup" };
171:
172: public int getColumnCount() {
173: return columnNames.length;
174: }
175:
176: public int getRowCount() {
177: return map.sizeFull() + 1;
178: }
179:
180: public StringBuffer getMemberNames(Member[] members) {
181: StringBuffer buf = new StringBuffer();
182: if (members != null) {
183: for (int i = 0; i < members.length; i++) {
184: buf.append(members[i].getName());
185: buf.append("; ");
186: }
187: }
188: return buf;
189: }
190:
191: public Object getValueAt(int row, int col) {
192: if (row == -1) {
193: update();
194: return "";
195: }
196: if (row == 0)
197: return columnNames[col];
198: Object[] keys = map.keySetFull().toArray();
199: String key = (String) keys[row - 1];
200: LazyReplicatedMap.MapEntry entry = map.getInternal(key);
201: switch (col) {
202: case 0:
203: return entry.getKey();
204: case 1:
205: return entry.getValue();
206: case 2:
207: return getMemberNames(entry.getBackupNodes());
208: case 3:
209: return new Boolean(entry.isPrimary());
210: case 4:
211: return new Boolean(entry.isProxy());
212: case 5:
213: return new Boolean(entry.isBackup());
214: default:
215: return "";
216: }
217:
218: }
219:
220: public void update() {
221: fireTableDataChanged();
222: }
223: };
224:
225: JTextField txtAddKey = new JTextField(20);
226: JTextField txtAddValue = new JTextField(20);
227: JTextField txtRemoveKey = new JTextField(20);
228: JTextField txtChangeKey = new JTextField(20);
229: JTextField txtChangeValue = new JTextField(20);
230:
231: JTable table = null;
232:
233: public SimpleTableDemo(LazyReplicatedMap map) {
234: super ();
235: this .map = map;
236:
237: this
238: .setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
239:
240: //final JTable table = new JTable(data, columnNames);
241: table = new JTable(dataModel);
242:
243: table.setPreferredScrollableViewportSize(new Dimension(
244: WIDTH, 150));
245: for (int i = 0; i < table.getColumnCount(); i++) {
246: TableColumn tm = table.getColumnModel().getColumn(i);
247: tm.setCellRenderer(new ColorRenderer());
248: }
249:
250: if (DEBUG) {
251: table.addMouseListener(new MouseAdapter() {
252: public void mouseClicked(MouseEvent e) {
253: printDebugData(table);
254: }
255: });
256: }
257:
258: //setLayout(new GridLayout(5, 0));
259: setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
260:
261: //Create the scroll pane and add the table to it.
262: JScrollPane scrollPane = new JScrollPane(table);
263:
264: //Add the scroll pane to this panel.
265: add(scrollPane);
266:
267: //create a add value button
268: JPanel addpanel = new JPanel();
269: addpanel.setPreferredSize(new Dimension(WIDTH, 30));
270: addpanel.add(createButton("Add", "add"));
271: addpanel.add(txtAddKey);
272: addpanel.add(txtAddValue);
273: addpanel.setMaximumSize(new Dimension(WIDTH, 30));
274: add(addpanel);
275:
276: //create a remove value button
277: JPanel removepanel = new JPanel();
278: removepanel.setPreferredSize(new Dimension(WIDTH, 30));
279: removepanel.add(createButton("Remove", "remove"));
280: removepanel.add(txtRemoveKey);
281: removepanel.setMaximumSize(new Dimension(WIDTH, 30));
282: add(removepanel);
283:
284: //create a change value button
285: JPanel changepanel = new JPanel();
286: changepanel.add(createButton("Change", "change"));
287: changepanel.add(txtChangeKey);
288: changepanel.add(txtChangeValue);
289: changepanel.setPreferredSize(new Dimension(WIDTH, 30));
290: changepanel.setMaximumSize(new Dimension(WIDTH, 30));
291: add(changepanel);
292:
293: //create sync button
294: JPanel syncpanel = new JPanel();
295: syncpanel.add(createButton("Synchronize", "sync"));
296: syncpanel.add(createButton("Replicate", "replicate"));
297: syncpanel.add(createButton("Random", "random"));
298: syncpanel.setPreferredSize(new Dimension(WIDTH, 30));
299: syncpanel.setMaximumSize(new Dimension(WIDTH, 30));
300: add(syncpanel);
301:
302: }
303:
304: public JButton createButton(String text, String command) {
305: JButton button = new JButton(text);
306: button.setActionCommand(command);
307: button.addActionListener(this );
308: return button;
309: }
310:
311: public void actionPerformed(ActionEvent e) {
312: System.out.println(e.getActionCommand());
313: if ("add".equals(e.getActionCommand())) {
314: System.out.println("Add key:" + txtAddKey.getText()
315: + " value:" + txtAddValue.getText());
316: map.put(txtAddKey.getText(), new StringBuffer(
317: txtAddValue.getText()));
318: }
319: if ("change".equals(e.getActionCommand())) {
320: System.out.println("Change key:"
321: + txtChangeKey.getText() + " value:"
322: + txtChangeValue.getText());
323: StringBuffer buf = (StringBuffer) map.get(txtChangeKey
324: .getText());
325: if (buf != null) {
326: buf.delete(0, buf.length());
327: buf.append(txtChangeValue.getText());
328: map.replicate(txtChangeKey.getText(), true);
329: } else {
330: buf = new StringBuffer();
331: buf.append(txtChangeValue.getText());
332: map.put(txtChangeKey.getText(), buf);
333: }
334: }
335: if ("remove".equals(e.getActionCommand())) {
336: System.out.println("Remove key:"
337: + txtRemoveKey.getText());
338: map.remove(txtRemoveKey.getText());
339: }
340: if ("sync".equals(e.getActionCommand())) {
341: System.out.println("Syncing from another node.");
342: map.transferState();
343: }
344: if ("random".equals(e.getActionCommand())) {
345: Thread t = new Thread() {
346: public void run() {
347: for (int i = 0; i < 100; i++) {
348: String key = Arrays.toString(UUIDGenerator
349: .randomUUID(false));
350: map.put(key, new StringBuffer(key));
351: dataModel.fireTableDataChanged();
352: table.paint(table.getGraphics());
353: try {
354: Thread.sleep(500);
355: } catch (InterruptedException x) {
356: Thread.currentThread().interrupted();
357: }
358: }
359: }
360: };
361: t.start();
362: }
363:
364: if ("replicate".equals(e.getActionCommand())) {
365: System.out
366: .println("Replicating out to the other nodes.");
367: map.replicate(true);
368: }
369: dataModel.getValueAt(-1, -1);
370: }
371:
372: private void printDebugData(JTable table) {
373: int numRows = table.getRowCount();
374: int numCols = table.getColumnCount();
375: javax.swing.table.TableModel model = table.getModel();
376:
377: System.out.println("Value of data: ");
378: for (int i = 0; i < numRows; i++) {
379: System.out.print(" row " + i + ":");
380: for (int j = 0; j < numCols; j++) {
381: System.out.print(" " + model.getValueAt(i, j));
382: }
383: System.out.println();
384: }
385: System.out.println("--------------------------");
386: }
387:
388: /**
389: * Create the GUI and show it. For thread safety,
390: * this method should be invoked from the
391: * event-dispatching thread.
392: */
393: public static SimpleTableDemo createAndShowGUI(
394: LazyReplicatedMap map, String title) {
395: //Make sure we have nice window decorations.
396: JFrame.setDefaultLookAndFeelDecorated(true);
397:
398: //Create and set up the window.
399: JFrame frame = new JFrame("SimpleTableDemo - " + title);
400: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
401:
402: //Create and set up the content pane.
403: SimpleTableDemo newContentPane = new SimpleTableDemo(map);
404: newContentPane.setOpaque(true); //content panes must be opaque
405: frame.setContentPane(newContentPane);
406:
407: //Display the window.
408: frame.setSize(450, 250);
409: newContentPane.setSize(450, 300);
410: frame.pack();
411: frame.setVisible(true);
412: return newContentPane;
413: }
414: }
415:
416: static class ColorRenderer extends DefaultTableCellRenderer {
417:
418: public ColorRenderer() {
419: super ();
420: }
421:
422: public Component getTableCellRendererComponent(JTable table,
423: Object value, boolean isSelected, boolean hasFocus,
424: int row, int column) {
425: Component cell = super .getTableCellRendererComponent(table,
426: value, isSelected, hasFocus, row, column);
427: cell.setBackground(Color.WHITE);
428: if (row > 0) {
429: Color color = null;
430: boolean primary = ((Boolean) table.getValueAt(row, 3))
431: .booleanValue();
432: boolean proxy = ((Boolean) table.getValueAt(row, 4))
433: .booleanValue();
434: boolean backup = ((Boolean) table.getValueAt(row, 5))
435: .booleanValue();
436: if (primary)
437: color = Color.GREEN;
438: else if (proxy)
439: color = Color.RED;
440: else if (backup)
441: color = Color.BLUE;
442: if (color != null)
443: cell.setBackground(color);
444: }
445: // System.out.println("Row:"+row+" Column:"+column+" Color:"+cell.getBackground());
446: // cell.setBackground(bkgndColor);
447: // cell.setForeground(fgndColor);
448:
449: return cell;
450: }
451:
452: }
453:
454: }
|