/******************************************************************************* *Copyright (c) 2009 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, only version 3 of the License. * * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. * * Please contact Eucalyptus Systems, Inc., 130 Castilian * Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> * if you need additional information or have any questions. * * This file may incorporate work covered under the following copyright and * permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF * THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE * LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS * SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA * BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN * THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT * OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR * WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH * ANY SUCH LICENSES OR RIGHTS. *******************************************************************************/ package edu.ucsb.eucalyptus.admin.client; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.*; import edu.ucsb.eucalyptus.admin.client.ClusterInfoTable.DeleteCallback; import edu.ucsb.eucalyptus.admin.client.SystemConfigTable.ChangeCallback; import edu.ucsb.eucalyptus.admin.client.SystemConfigTable.FocusHandler; import java.util.ArrayList; import java.util.List; // dmitrii TODO: remove commented out lines once the CSS-based design is confirmed public class WalrusInfoTable extends VerticalPanel implements ClickHandler { private static int maxWalruses = 1; // TODO: bump this up once we can do more than 1 private static Label noWalrusesLabel = new Label(); private static Label statusLabel = new Label(); private Grid grid = new Grid (); private EucaButton add_button = new EucaButton ( "Register Walrus", this ); private static HTML hint = new HTML (); private List<WalrusInfoWeb> walrusList = new ArrayList<WalrusInfoWeb>(); private static String sessionId; private static String warningMessage = "Note: registering Walrus requires synchronization of keys among all nodes, which cannot be done through this interface. See documentation for details."; public WalrusInfoTable(String sessionId) { this.sessionId = sessionId; this.setStyleName("euca-config-component"); this.setSpacing (2); this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); // this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); Label walrusesHeader = new Label( "Walrus Configuration:" ); walrusesHeader.setStyleName ( "euca-section-header" ); this.add ( walrusesHeader ); this.noWalrusesLabel.setText ("No Walrus hosts registered"); this.noWalrusesLabel.setStyleName ("euca-greeting-disabled"); HorizontalPanel grid_and_hint = new HorizontalPanel (); grid_and_hint.add ( this.grid ); grid_and_hint.add ( this.hint ); this.hint.setWidth ("100"); this.add ( grid_and_hint ); HorizontalPanel hpanel = new HorizontalPanel (); hpanel.setSpacing (2); hpanel.add ( add_button ); hpanel.add ( new EucaButton( "Save Walrus configuration", new SaveCallback( this ) ) ); hpanel.add ( this.statusLabel ); // this.statusLabel.setWidth ("250"); this.statusLabel.setText (""); this.statusLabel.setStyleName ("euca-greeting-pending"); this.add ( hpanel ); rebuildTable(); EucalyptusWebBackend.App.getInstance().getWalrusList( this.sessionId, new GetWalrusListCallback( this ) ); } public void onClick( ClickEvent event ) // Register walrus button { this.walrusList.add (new WalrusInfoWeb("Walrus", "host", 8773 /** FIXME: DRAMATICALLY: URGENTLY **/, new ArrayList<String>())); //these values are just defaults this.rebuildTable(); this.statusLabel.setText ("Unsaved changes"); this.statusLabel.setStyleName ("euca-greeting-warning"); } private void rebuildTable() { if (this.walrusList.isEmpty()) { this.grid.setVisible (false); this.noWalrusesLabel.setVisible (true); this.add_button.setEnabled (true); } else { this.noWalrusesLabel.setVisible (false); this.grid.clear (); this.grid.resize ( this.walrusList.size(), 1 ); this.grid.setVisible (true); this.grid.setStyleName( "euca-table" ); this.grid.setCellPadding( 2 ); int row = 0; for ( WalrusInfoWeb w : this.walrusList ) { /*// big yellow block looks kinda weird if ( ( row % 2 ) == 1 ) { this.grid.getRowFormatter().setStyleName( row, "euca-table-even-row" ); } else { this.grid.getRowFormatter().setStyleName( row, "euca-table-odd-row" ); }*/ this.grid.setWidget (row, 0, addWalrusEntry (row++, w)); } if ( row >= maxWalruses ) { this.add_button.setEnabled (false); } else { this.add_button.setEnabled (true); } } } private Grid addWalrusEntry ( int row, WalrusInfoWeb walrusInfo) { final ArrayList<String> properties = walrusInfo.getProperties(); int numProperties = properties.size() / 4; Grid g = new Grid (1 + numProperties, 2); g.setStyleName( "euca-table" ); g.setCellPadding( 4 ); int i = 0; // row 1 g.setWidget( i, 0, new Label( "Walrus host:" ) ); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); HorizontalPanel p = new HorizontalPanel (); p.setSpacing(0); g.setWidget( i, 1, p ); final TextBox walrusHost_box = new TextBox(); walrusHost_box.addChangeListener (new ChangeCallback (this, row)); walrusHost_box.setVisibleLength(35); walrusHost_box.setText (walrusInfo.getHost()); p.add (walrusHost_box); p.add (new EucaButton ("Deregister", new DeleteCallback( this, row ))); for(int propIdx = 0 ; propIdx < numProperties ; ++propIdx) { i++; // next row if ("KEYVALUE".equals(properties.get(4 * propIdx))) { g.setWidget( i, 0, new Label(properties.get(4*propIdx + 1) + ": ") ); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox propTextBox = new TextBox(); propTextBox.addChangeListener (new ChangeCallback (this, row)); propTextBox.setVisibleLength( 30 ); propTextBox.setText(properties.get(4*propIdx + 2)); propTextBox.addFocusListener (new FocusHandler (this.hint, this.warningMessage)); g.setWidget( i, 1, propTextBox ); } else if ("KEYVALUEHIDDEN".equals(properties.get(4 * propIdx))) { g.setWidget( i, 0, new Label(properties.get(4*propIdx + 1) + ": ") ); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox propTextBox = new PasswordTextBox(); propTextBox.addChangeListener (new ChangeCallback (this, row)); propTextBox.setVisibleLength( 30 ); propTextBox.setText(properties.get(4*propIdx + 2)); propTextBox.addFocusListener (new FocusHandler (this.hint, this.warningMessage)); g.setWidget( i, 1, propTextBox ); } else if("BOOLEAN".equals(properties.get(4 * propIdx))) { final int index = propIdx; final CheckBox propCheckbox = new CheckBox (); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); g.setWidget( i, 0, propCheckbox ); if (Boolean.parseBoolean(properties.get(4*index + 2))) { propCheckbox.setChecked(true); } else { propCheckbox.setChecked(false); } propCheckbox.addClickListener (new ClickListener() { public void onClick( Widget sender ) { if (((CheckBox)sender).isChecked()) { properties.set(4 * index + 2, String.valueOf(true) ); } else { properties.set(4 * index + 2, String.valueOf(false) ); } } }); g.setWidget( i, 1, new Label (properties.get(propIdx * 4 + 1)) ); } } return g; } public List<WalrusInfoWeb> getWalrusList() { return walrusList; } public void setWalrusList ( final List<WalrusInfoWeb> walrusList ) { this.walrusList = walrusList; } public void updateRow (int row) { WalrusInfoWeb walrus = this.walrusList.get (row); Grid g = (Grid)this.grid.getWidget(row, 0); HorizontalPanel p = (HorizontalPanel)g.getWidget(0, 1); walrus.setHost (((TextBox)p.getWidget(0)).getText()); int widgetStartIndex = 1; ArrayList<String> properties = walrus.getProperties(); for(int i = 0; i < (properties.size() / 4); ++i) { if(properties.get(4*i).startsWith("KEYVALUE")) properties.set(4*i + 2, ((TextBox)g.getWidget(widgetStartIndex + i, 1)).getText()); } } public void MarkCommitted () { for ( WalrusInfoWeb walrus : this.walrusList ) { walrus.setCommitted (); } } class ChangeCallback implements ChangeListener, ClickListener { private WalrusInfoTable parent; private int row; ChangeCallback ( final WalrusInfoTable parent, final int row ) { this.parent = parent; this.row = row; } public void onChange (Widget sender) { this.parent.updateRow (this.row); this.parent.statusLabel.setText ("Unsaved changes"); this.parent.statusLabel.setStyleName ("euca-greeting-warning"); } public void onClick (Widget sender) { this.parent.updateRow (this.row); this.parent.statusLabel.setText ("Unsaved changes"); this.parent.statusLabel.setStyleName ("euca-greeting-warning"); } } class DeleteCallback implements ClickHandler { private WalrusInfoTable parent; private int row; DeleteCallback( final WalrusInfoTable parent, final int row ) { this.parent = parent; this.row = row; } public void onClick( ClickEvent event ) { this.parent.walrusList.remove (this.row); this.parent.rebuildTable(); this.parent.statusLabel.setText ("Unsaved changes"); this.parent.statusLabel.setStyleName ("euca-greeting-warning"); } } class GetWalrusListCallback implements AsyncCallback { private WalrusInfoTable parent; GetWalrusListCallback( final WalrusInfoTable parent ) { this.parent = parent; } public void onFailure( final Throwable throwable ) { this.parent.statusLabel.setText ("Failed to contact server!"); this.parent.statusLabel.setStyleName ("euca-greeting-error"); } public void onSuccess( final Object o ) { List<WalrusInfoWeb> newWalrusList = (List<WalrusInfoWeb>) o; this.parent.statusLabel.setText ("Walrus configuration up to date"); this.parent.statusLabel.setStyleName ("euca-greeting-disabled"); this.parent.walrusList = newWalrusList; this.parent.MarkCommitted(); this.parent.rebuildTable(); } } class SaveCallback implements AsyncCallback, ClickHandler { private WalrusInfoTable parent; SaveCallback( final WalrusInfoTable parent ) { this.parent = parent; } public void onClick( ClickEvent event ) { this.parent.statusLabel.setText ("Saving..."); this.parent.statusLabel.setStyleName ("euca-greeting-pending"); EucalyptusWebBackend.App.getInstance().setWalrusList( this.parent.sessionId, this.parent.walrusList, this ); } public void onFailure( final Throwable throwable ) { this.parent.statusLabel.setText ("Failed to save! (Check hostname and path.)"); this.parent.statusLabel.setStyleName ("euca-greeting-error"); } public void onSuccess( final Object o ) { this.parent.statusLabel.setText ("Saved Walrus configuration to server"); this.parent.statusLabel.setStyleName ("euca-greeting-disabled"); this.parent.MarkCommitted (); this.parent.rebuildTable(); // so the committed ones show up } } class FocusHandler implements FocusListener { private HTML parent; private String message; FocusHandler (final HTML parent, String message) { this.parent = parent; this.message = message; } public void onLostFocus (Widget sender) { this.parent.setHTML (""); this.parent.setStyleName ("euca-text"); } public void onFocus (Widget sender) { this.parent.setHTML (message); this.parent.setStyleName ("euca-error-hint"); } } }