Hi Artur,
I can’t really make sense of what you say… If you have some time, please see the attached code for my main application and custom view (just simple tests and proof-of-concepts so far).
Cheers,
Candide
package com.fluxtream.ui.mgmt;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import com.fluxtream.domain.Guest;
import com.fluxtream.services.GuestService;
import com.fluxtream.services.XmppService;
import com.fluxtream.ui.AbstractView;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.Label;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
/**
* TODO Document me!
* @author Candide Kemmler
*
*/
public class HomeView extends AbstractView {
private static final long serialVersionUID = -8421758733452231380L;
public HomeView(FlxMgmtApp application, GuestService guestService) {
super(application);
this.guestService = guestService;
init();
}
public static final String USERNAME_PROPERTY = "username";
public static final String FIRSTNAME_PROPERTY = "firstname";
public static final String LASTNAME_PROPERTY = "lastname";
public static final String PRESENCE_PROPERTY = "presence";
GuestService guestService;
Container guestDatasource;
private Presence currentPresence;
protected XMPPConnection connection;
MessageListener messageListener;
Table table;
public boolean connect(String server, Integer port, Map<String, String> parameters) throws XMPPException {
final ConnectionConfiguration config = new ConnectionConfiguration(server, port);
connection = new XMPPConnection(config);
connection.connect();
messageListener = new MessageListener();
connection.addPacketListener(messageListener, new PacketTypeFilter(Message.class));
return true;
}
private class MessageListener implements PacketListener {
@Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
@SuppressWarnings("unused")
Message message = (Message) packet;
}
}
}
protected void initXmpp() throws XMPPException {
connect(XmppService.XMPP_HOSTNAME, XmppService.XMPP_PORT, new HashMap<String,String>());
connection.login(XmppService.ADMIN_JID, XmppService.ADMIN_PWD);
setPresenceMode(Presence.Type.available, Presence.Mode.available);
}
public void setPresenceMode(Presence.Type pres, Presence.Mode mod){
currentPresence = new Presence(pres);
currentPresence.setMode(mod);
// Send the packet
connection.sendPacket(currentPresence);
}
public Presence getContactPresence(String user){
Roster roster = connection.getRoster();
return roster.getPresence(user);
}
@SuppressWarnings("serial")
protected void init() {
final AbsoluteLayout mainLayout = new AbsoluteLayout();
mainLayout.setWidth("100%");
mainLayout.setHeight("100%");
table = new Table("All Users");
mainLayout.addComponent(table);
table.setSelectable(true);
table.setMultiSelect(true);
table.setImmediate(true); // react at once when something is selected
table.setWidth("100%");
table.setHeight("100%");
List<Guest> allGuests = guestService.getAllGuests();
guestDatasource = getGuestDatasource(allGuests);
table.setContainerDataSource(guestDatasource );
table.addGeneratedColumn(PRESENCE_PROPERTY, new Table.ColumnGenerator() {
@Override
public Component generateCell(Table source, Object itemId, Object columnId) {
Item item = source.getItem(itemId);
Property itemProperty = item.getItemProperty(PRESENCE_PROPERTY);
Boolean online = (Boolean)itemProperty.getValue();
return new Embedded("",new ThemeResource(online?"icons/16/online.png":"icons/16/offline.png"));
}
});
SplitPanel splitpanel = new SplitPanel();
splitpanel.setSizeFull();
splitpanel.setWidth("100%");
// Set the orientation.
splitpanel.setOrientation(SplitPanel.ORIENTATION_HORIZONTAL);
// Put two components in the container.
splitpanel.setFirstComponent(table);
splitpanel.setSplitPosition(200, SplitPanel.UNITS_PIXELS);
TabSheet t = addTabs();
splitpanel.setSecondComponent(t);
mainLayout.addComponent(splitpanel);
setCompositionRoot(mainLayout);
try {
initXmpp();
} catch (XMPPException e) {
e.printStackTrace();
}
}
private TabSheet addTabs() {
TabSheet t = new TabSheet();
t.setHeight("100%");
t.setWidth("100%");
VerticalLayout l1 = new VerticalLayout();
l1.setMargin(true);
l1.addComponent(new Label("bla bla."));
// Tab 2 content
VerticalLayout l2 = new VerticalLayout();
l2.setMargin(true);
l2.addComponent(new Label("There are no saved notes."));
// Tab 3 content
VerticalLayout l3 = new VerticalLayout();
l3.setMargin(true);
l3.addComponent(new Label("There are currently no issues."));
// Tab 4 content
VerticalLayout l4 = new VerticalLayout();
l4.setMargin(true);
l4.addComponent(new Label("There are no comments."));
// Tab 5 content
VerticalLayout l5 = new VerticalLayout();
l5.setMargin(true);
setupDebugPanel(l5);
VerticalLayout l6 = new VerticalLayout();
l6.setMargin(true);
setupDebugPanel(l6);
t.addTab(l1, "History", null);
t.addTab(l2, "Profile", null);
t.addTab(l3, "Notes", null);
t.addTab(l4, "Comments", null);
t.addTab(l5, "Feedback", null);
t.addTab(l6, "Debug", null);
return t;
}
Label dbgLabel;
private void setupDebugPanel(final VerticalLayout l6) {
dbgLabel = new Label("void");
dbgLabel.setValue("alors, ça marche?");
l6.addComponent(dbgLabel);
Button button = new Button("Ask subscription");
button.addListener(new ClickListener() {
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event) {
Presence currentPresence = new Presence(Presence.Type.subscribe);
currentPresence.setFrom("sirius@fluxtream.com");
currentPresence.setTo("ckemmler@gmail.com");
XMPPConnection conn = connection;
conn.sendPacket(currentPresence);
}
});
l6.addComponent(button);
Button chatbutton = new Button("Chat");
chatbutton.addListener(new ClickListener() {
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event) {
Chat chat = connection.getChatManager().createChat("ckemmler@gmail.com", null);
try {
chat.sendMessage("haha");
} catch (XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
l6.addComponent(chatbutton);
Button pushbutton = new Button("Push");
pushbutton.addListener(new ClickListener() {
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event) {
List<Guest> allGuests = guestService.getAllGuests();
guestDatasource = getGuestDatasource(allGuests);
Container containerDataSource = table.getContainerDataSource();
Item item = containerDataSource.getItem(containerDataSource.getItemIds().iterator().next());
boolean online = (Boolean) item.getItemProperty(PRESENCE_PROPERTY).getValue();
item.getItemProperty(PRESENCE_PROPERTY).setValue(!online);
table.setContainerDataSource(containerDataSource);
getApplication().push();
}
});
l6.addComponent(pushbutton);
}
private Container getGuestDatasource(List<Guest> allGuests) {
IndexedContainer c = new IndexedContainer();
c.addContainerProperty(USERNAME_PROPERTY, String.class, null);
c.addContainerProperty(PRESENCE_PROPERTY, Boolean.class, null);
for (Guest guest : allGuests) {
Item guestItem = c.addItem(guest.getId());
guestItem.getItemProperty(USERNAME_PROPERTY).setValue(guest.getUsername());
guestItem.getItemProperty(PRESENCE_PROPERTY).setValue(false);
}
return c;
}
}
/*
* Copyright (c) 2010 The original author(s)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fluxtream.ui.mgmt;
import java.util.Locale;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.vaadin.artur.icepush.ICEPush;
import com.fluxtream.VersionInfo;
import com.fluxtream.services.GuestService;
import com.fluxtream.ui.I18nProvider;
import com.fluxtream.ui.LoginView;
import com.vaadin.Application;
import com.vaadin.service.ApplicationContext.TransactionListener;
import com.vaadin.ui.Component.Event;
import com.vaadin.ui.Window;
@Component("applicationBean")
@Scope("prototype")
public class FlxMgmtApp extends Application implements I18nProvider,
TransactionListener {
private static final long serialVersionUID = -1412284137848857188L;
ICEPush pusher;
/**
* Apache Commons logger for logging stuff.
*/
protected final Log logger = LogFactory.getLog(getClass());
@Resource
private MessageSource messages;
@Resource
private AuthenticationManager authenticationManager;
@Resource
private GuestService guestService;
private LoginView loginView;
private static final Locale[] SUPPORTED_LOCALES = { Locale.US,
new Locale("fi", "FI"), new Locale("sv", "SE") };
private static final String[] LOCALE_NAMES = { "English", "Suomi",
"Svenska" };
@Override
public Locale getLocale() {
/*
* Fetch the locale resolved by Spring in the application servlet
*/
return LocaleContextHolder.getLocale();
}
@Override
public void setLocale(Locale locale) {
LocaleContextHolder.setLocale(locale);
}
public void push() {
if (this.pusher==null) {
this.pusher = new ICEPush();
getMainWindow().addComponent(pusher);
}
this.pusher.push();
}
@SuppressWarnings("serial")
@Override
public void init() {
if (logger.isDebugEnabled()) {
logger.debug("Initializing application [" + this + "]
");
}
// Register listener
getContext().addTransactionListener(this);
// Create the views
loginView = new LoginView(this, authenticationManager);
loginView.setSizeFull();
setTheme("flx"); // We use a custom theme
final Window loginWindow = new Window(getMessage("app.title",
getVersion()), loginView);
setMainWindow(loginWindow);
loginView.addListener(new com.vaadin.ui.Component.Listener() {
@Override
public void componentEvent(Event event) {
if (event instanceof LoginView.LoginEvent) {
if (logger.isDebugEnabled()) {
logger.debug("User logged on ["
+ ((LoginView.LoginEvent) event)
.getAuthentication() + "]");
}
/*
* A user has logged on, which means we can ditch the login
* view and open the main view instead. We also have to
* update the security context holder.
*/
setUser(((LoginView.LoginEvent) event).getAuthentication());
SecurityContextHolder.getContext().setAuthentication(
((LoginView.LoginEvent) event).getAuthentication());
removeWindow(loginWindow);
loginView = null;
HomeView homeView = new HomeView(FlxMgmtApp.this,
guestService);
homeView.setSizeFull();
Window mainWindow = new Window(getMessage("app.title",
getVersion()), homeView);
setMainWindow(mainWindow);
}
}
});
}
@Override
@PreDestroy
// In case the application is destroyed by the container
public void close() {
if (logger.isDebugEnabled()) {
logger.debug("Closing application [" + this + "]
");
}
// Clear the authentication property to log the user out
setUser(null);
// Also clear the security context
SecurityContextHolder.clearContext();
getContext().removeTransactionListener(this);
super.close();
}
@Override
protected void finalize() throws Throwable {
if (logger.isDebugEnabled()) {
/*
* This is included to make sure that closed applications get
* properly garbage collected.
*/
logger.debug("Garbage collecting application [" + this + "]
");
}
super.finalize();
}
@Override
public void transactionEnd(Application application, Object transactionData) {
if (logger.isDebugEnabled()) {
logger
.debug("Transaction ended, removing authentication data from security context");
}
/*
* The purpose of this
*/
SecurityContextHolder.getContext().setAuthentication(null);
}
@Override
public void transactionStart(Application application, Object transactionData) {
if (logger.isDebugEnabled()) {
logger
.debug("Transaction started, setting authentication data of security context to ["
+ application.getUser() + "]");
}
/*
* The security context holder uses the thread local pattern to store
* its authentication credentials. As requests may be handled by
* different threads, we have to update the security context holder in
* the beginning of each transaction.
*/
SecurityContextHolder.getContext().setAuthentication(
(Authentication) application.getUser());
}
/**
* Gets the currently logged in user. If this value is <code>null</code>, no
* user has been logged in yet.
*
* @return an {@link Authentication} instance.
*/
@Override
public Authentication getUser() {
return (Authentication) super.getUser();
}
@Override
public String getVersion() {
return VersionInfo.getApplicationVersion();
}
@Override
public String getMessage(String code, Object... args)
throws NoSuchMessageException {
return messages.getMessage(code, args, getLocale());
}
@Override
public Locale[] getSupportedLocales() {
return SUPPORTED_LOCALES;
}
@Override
public String getLocaleDisplayName(Locale locale) {
for (int i = 0; i < SUPPORTED_LOCALES.length; i++) {
if (locale.equals(SUPPORTED_LOCALES[i]
)) {
return LOCALE_NAMES[i]
;
}
}
return "Unsupported Locale";
}
}