/*
* Copyright 2009 IT Mill Ltd.
*
* 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.thingtrack.konekti.view.web.workbench;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.dellroad.stuff.vaadin.SpringContextApplication;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.wiring.BundleWiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import com.github.peholmst.i18n4vaadin.I18N;
import com.github.peholmst.i18n4vaadin.ResourceBundleI18N;
import com.thingtrack.konekti.domain.Action;
import com.thingtrack.konekti.domain.Configuration;
import com.thingtrack.konekti.domain.MenuCommandResource;
import com.thingtrack.konekti.domain.MenuFolderResource;
import com.thingtrack.konekti.domain.MenuResource;
import com.thingtrack.konekti.domain.MenuWorkbench;
import com.thingtrack.konekti.domain.Permission;
import com.thingtrack.konekti.domain.Role;
import com.thingtrack.konekti.domain.User;
import com.thingtrack.konekti.service.api.AreaService;
import com.thingtrack.konekti.service.api.ConfigurationService;
import com.thingtrack.konekti.service.api.LocationService;
import com.thingtrack.konekti.service.api.MenuWorkbenchService;
import com.thingtrack.konekti.service.api.OrganizationService;
import com.thingtrack.konekti.service.api.UserService;
import com.thingtrack.konekti.service.security.SecurityService;
import com.thingtrack.konekti.view.addon.ui.SliderView;
import com.thingtrack.konekti.view.kernel.IMetadataModuleServiceListener;
import com.thingtrack.konekti.view.kernel.IModuleService;
import com.thingtrack.konekti.view.kernel.IWorkbenchContext;
import com.thingtrack.konekti.view.kernel.MetadataModule;
import com.thingtrack.konekti.view.kernel.ui.layout.IApplicationCloseEventListener;
import com.thingtrack.konekti.view.kernel.ui.layout.IUserChangeListener;
import com.thingtrack.konekti.view.kernel.ui.layout.IViewChangeListener;
import com.thingtrack.konekti.view.kernel.ui.layout.IViewContainer;
import com.thingtrack.konekti.view.kernel.ui.layout.LOCATION;
import com.thingtrack.konekti.view.kernel.ui.layout.ViewEvent;
import com.thingtrack.konekti.view.layout.KonektiLayout;
import com.thingtrack.konekti.view.web.workbench.ui.MenuManager;
import com.thingtrack.konekti.view.web.workbench.ui.ResourceManager;
import com.thingtrack.konekti.view.web.workbench.ui.ResourceManager.Resource;
import com.thingtrack.konekti.view.web.workbench.ui.ToolbarManager;
import com.thingtrack.konekti.view.web.workbench.ui.WorkbenchContext;
import com.thingtrack.konekti.view.web.form.field.LocaleField;
import com.thingtrack.konekti.view.addon.ui.ErrorViewForm;
import com.vaadin.terminal.StreamResource;
import com.vaadin.terminal.StreamResource.StreamSource;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
/**
* The Application's "main" class
*/
@SuppressWarnings("serial")
public class Main extends SpringContextApplication implements IMetadataModuleServiceListener, IViewChangeListener, IUserChangeListener {
private final static Logger logger = Logger.getLogger(SpringContextApplication.class.getName());
@Autowired
private IModuleService moduleService;
@Autowired
private MenuWorkbenchService menuWorkbenchService;
@Autowired
private SecurityService securityService;
@Autowired
private OrganizationService organizationService;
@Autowired
private LocationService locationService;
@Autowired
private AreaService areaService;
@Autowired
private UserService userService;
@Autowired
private ConfigurationService configurationService;
@Autowired
private ResourceManager resourceManager;
@Autowired
private ToolbarManager toolbarManager;
@Autowired
private MenuManager menuManager;
@Autowired
private KonektiLayout konektiLayout;
private MainWindow window;
private SliderView sliderView;
private IWorkbenchContext workbenchContext;
private String name;
private String version;
private String logoInit;
private boolean demo;
private boolean jira;
private String jiraURL;
private static int DEFAULT_MENU_ID = 0;
private MenuItem headMenuItem;
private I18N i18n;
@Override
protected void initSpringApplication(ConfigurableWebApplicationContext context) {
// set konekti theme
setTheme("konekti");
// get global konekti configuration
getConfiguration();
// set main Window
window = new MainWindow(name, configureI18n());
window.setStyleName("background");
setMainWindow(window);
// set full size and none margin for the default window layout
VerticalLayout mainLayout = (VerticalLayout) window.getContent();
mainLayout.setSizeFull();
mainLayout.setMargin(false);
// Create the views
createViews();
// add Konekti Layout
mainLayout.addComponent(sliderView);
// add module listener to list bundle install/uninstall
moduleService.addListener(this);
// add user change listener
konektiLayout.getMenuLayout().addListenerUserChange(this);
// set jira issue collector button
generateJIRAIssueCollector();
// define MenuLayout Message listeners
konektiLayout.getMenuLayout().addListenerApplicationClose(new IApplicationCloseEventListener() {
@Override
public void close() {
moduleService.removeListener(Main.this);
WebApplicationContext webApplicationContext = (WebApplicationContext) getMainWindow().getApplication().getContext();
webApplicationContext.getHttpSession().invalidate();
getMainWindow().getApplication().close();
}
});
}
// Overriding getWindow(String) is required to get multiple browser windows/tabs to work
/*@Override
public Window getWindow(String name) {
// If the window is identified by name, we are good to go
Window w = super.getWindow(name);
// If not, we must create a new window for this new browser window/tab
if (w == null) {
//w = new CalcWindow();
w = new MainWindow(name, configureI18n());
// Use the random name given by the framework to identify this
// window in future
w.setName(name);
addWindow(w);
// Move to the url to remember the name in the future
w.open(new ExternalResource(w.getURL()));
}
return w;
}*/
private I18N configureI18n() {
// set locales supported by Konekti
Locale esLocale = new Locale("es");
Locale enLocale = new Locale("en");
Locale frLocale = new Locale("fr");
Locale zhLocale = new Locale("zh");
// configure locale sources
i18n = new ResourceBundleI18N("com/thingtrack/konekti/view/web/i18n/messages", getBundleClassLoader(), esLocale, enLocale, frLocale, zhLocale);
// set default locale from browser configuration
if (getLocale().toString().contains("es"))
i18n.setCurrentLocale(esLocale);
else if (getLocale().toString().contains("en"))
i18n.setCurrentLocale(enLocale);
else if (getLocale().toString().contains("fr"))
i18n.setCurrentLocale(frLocale);
else if (getLocale().toString().contains("zh"))
i18n.setCurrentLocale(zhLocale);
else
i18n.setCurrentLocale(esLocale);
return i18n;
}
private void generateJIRAIssueCollector() {
// set jira issue collector button
if (jira) {
StringBuffer buffer = new StringBuffer();
buffer.append("jQuery.ajax({");
buffer.append("url: \"" + jiraURL + "\"");
buffer.append(",type: \"get\"");
buffer.append(",cache: true");
buffer.append(",dataType: \"script\"});");
getMainWindow().executeJavaScript(buffer.toString());
}
}
private ClassLoader getBundleClassLoader() {
BundleContext bundleContext = FrameworkUtil.getBundle(Main.class).getBundleContext();
Bundle bundle = bundleContext.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ClassLoader classLoader = bundleWiring.getClassLoader();
return classLoader;
}
private void getConfiguration() {
Configuration configuration = null;
try {
configuration = configurationService.getByTag(Configuration.TAG.NAME.name());
name = configuration.getValue();
} catch (Exception e) {
name = "KONEKTI";
}
try {
configuration = configurationService.getByTag(Configuration.TAG.VERSION.name());
version = configuration.getValue();
} catch (Exception e) {
version = "0.0.1.SNAPSHOT";
}
try {
configuration = configurationService.getByTag(Configuration.TAG.LOGO_INIT.name());
logoInit = configuration.getValue();
} catch (Exception e) {
logoInit = "logo_konekti_init.png";
}
try {
configuration = configurationService.getByTag(Configuration.TAG.DEMO.name());
demo = Boolean.parseBoolean(configuration.getValue());
} catch (Exception e) {
demo = false;
}
try {
configuration = configurationService.getByTag("JIRA");
jira = Boolean.parseBoolean(configuration.getValue());
} catch (Exception e) {
jira = false;
}
try {
configuration = configurationService.getByTag("JIRA_URL");
jiraURL = configuration.getValue();
} catch (Exception e) {
// konekti issueCollector
jiraURL = "https://thingtrack.atlassian.net/s/6791a7bea4f8d576fd0a266972dba049-T/es_ES-nr1nwy/64001/71/1.4.13/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=es-ES&collectorId=5e180215";
}
}
private void createViews() {
sliderView = new SliderView();
sliderView.addListener(this);
sliderView.addView(new SecurityAccessView(securityService, userService, sliderView, version, logoInit, demo));
sliderView.addView(new WorkbenchView(konektiLayout, sliderView));
}
protected void initMenuManager(User user) {
try {
// STEP 1: construct vertical menu
List<MenuWorkbench> menuResources = menuWorkbenchService.getAll();
// get the first menu
MenuWorkbench menuDefault = menuResources.get(DEFAULT_MENU_ID);
for (MenuFolderResource menuFolderResource : menuDefault.getMenuFolderResource()) {
// add new menu item
headMenuItem = konektiLayout.getMenuLayout()
.addMenuItem(
i18n.getMessage(menuFolderResource.getKeyCaption()),
getIcon(menuFolderResource.getIcon(),
menuFolderResource.getCaption()), null);
// recursive menu manage
getMenu(menuFolderResource, headMenuItem, user);
// remove menu items if don't have any command
if (!headMenuItem.hasChildren())
konektiLayout.getMenuLayout().removeItem(headMenuItem);
}
} catch (Exception e) {
e.getMessage();
}
}
private void getMenu(MenuFolderResource menuFolderResource, MenuItem itemParentId, User user) {
for (final MenuResource menuResource : menuFolderResource.getMenuResources()) {
if (menuResource instanceof MenuFolderResource) {
// add new submenu item
MenuItem headMenuResourceItem = konektiLayout.getMenuLayout().addMenuItem(
i18n.getMessage(menuFolderResource.getKeyCaption()),
getIcon(menuResource.getIcon(),menuResource.getCaption()),
itemParentId, null);
// recursive menu manage
getMenu((MenuFolderResource) menuResource, headMenuResourceItem, user);
// remove submenu items if don't have any command
if (!headMenuResourceItem.hasChildren())
itemParentId.removeChild(headMenuResourceItem);
} else {
if (((MenuCommandResource) menuResource).getType() == MenuCommandResource.TYPE.SEPARATOR)
itemParentId.addSeparator();
else {
// check if exist VIEW permission for each module for the active user role
if (getCommandPermission(user, (MenuCommandResource) menuResource)) {
// default menu command
Command defaultCommand = new Command() {
@Override
public void menuSelected(MenuItem selectedItem) {
window.showNotification(
"Module Warning",
"The Module: "
+ ((MenuCommandResource) menuResource)
.getModuleId()
+ "["
+ ((MenuCommandResource) menuResource)
.getModuleVersion()
+ "] is not deploy",
Window.Notification.TYPE_WARNING_MESSAGE);
}
};
// create the new menu item; recover commanda data
String symbolicName = ((MenuCommandResource) menuResource).getModuleId();
String version = ((MenuCommandResource) menuResource).getModuleVersion();
String id = symbolicName + "#" + version;
String caption = i18n.getMessage(((MenuCommandResource) menuResource).getKeyCaption());
String hint = i18n.getMessage(((MenuCommandResource) menuResource).getKeyHint());
boolean autoStart = ((MenuCommandResource) menuResource).isAutostart();
boolean closeable = ((MenuCommandResource) menuResource).isClosable();
com.vaadin.terminal.Resource resource = null;
if (((MenuCommandResource) menuResource) != null)
resource = getIcon(((MenuCommandResource) menuResource).getIcon(), caption);
// create the new menu item
MenuItem headMenuItem = konektiLayout.getMenuLayout().addMenuItem(caption, hint, resource, itemParentId, defaultCommand);
// add command to the menu manager list
if (((MenuCommandResource) menuResource).getLocation().name().equals("TOP"))
resourceManager.addResource(id, caption, resource, LOCATION.TOP, autoStart, closeable, null, headMenuItem, null);
else if (((MenuCommandResource) menuResource).getLocation().name().equals("LEFT"))
resourceManager.addResource(id, caption, resource, LOCATION.LEFT, autoStart, closeable, null, headMenuItem, null);
else if (((MenuCommandResource) menuResource).getLocation().name().equals("CENTER"))
resourceManager.addResource(id, caption, resource, LOCATION.CENTER, autoStart, closeable, null, headMenuItem, null);
else if (((MenuCommandResource) menuResource).getLocation().name().equals("RIGHT"))
resourceManager.addResource(id, caption, resource, LOCATION.RIGHT, autoStart, closeable, null, headMenuItem, null);
else if (((MenuCommandResource) menuResource).getLocation().name().equals("BOTTON"))
resourceManager.addResource(id, caption, resource, LOCATION.BOTTON, autoStart, closeable, null, headMenuItem, null);
// set module payload if is register in service registry
MetadataModule metadataModule = moduleService.get(symbolicName, version);
if (metadataModule != null) {
try {
setModuleResource(metadataModule);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
}
private StreamResource getIcon(final byte[] byteResource, String name) {
if (byteResource == null)
return null;
// create an instance of our stream source.
StreamSource imagesource = new ModuleResource(byteResource);
// Create a resource that uses the stream source and give it a name.
// The constructor will automatically register the resource in the
// application.
StreamResource imageresource = new StreamResource(imagesource, name
+ ".png", this);
return imageresource;
}
private class ModuleResource implements StreamResource.StreamSource {
private byte[] resource = null;
private ByteArrayOutputStream imagebuffer = null;
public ModuleResource(byte[] resource) {
this.resource = resource;
}
@Override
public InputStream getStream() {
if (resource != null) {
InputStream in = new ByteArrayInputStream(resource);
BufferedImage bImageFromConvert = null;
try {
bImageFromConvert = ImageIO.read(in);
imagebuffer = new ByteArrayOutputStream();
ImageIO.write(bImageFromConvert, "png", imagebuffer);
} catch (IOException e) {
e.printStackTrace();
}
return new ByteArrayInputStream(imagebuffer.toByteArray());
}
return null;
}
}
private void setModuleResource(MetadataModule metadataModule) throws Exception {
final Resource resource = resourceManager.getResource(metadataModule.getId() + "#" + metadataModule.getVersion());
if (resource != null) {
IViewContainer viewContainer = metadataModule.getModule().createViewComponent(workbenchContext);
viewContainer.addListener((IViewChangeListener) toolbarManager);
resource.setComponentView(viewContainer);
// set command (handler) to item menu
resource.getMenu().setCommand(new Command() {
@Override
public void menuSelected(MenuItem selectedItem) {
konektiLayout.addModule(resource.getId(),
resource.getCaption(), resource.getComponentView(), resource.isCloseable(),
resource.getResource(), resource.getLocation());
}
});
// autostart if the flag is active
if (resource.isAutoStart())
konektiLayout.addModule(resource.getId(),
resource.getCaption(), resource.getComponentView(), resource.isCloseable(),
resource.getResource(), resource.getLocation());
}
}
private Boolean getCommandPermission(User user, MenuCommandResource command) {
for (Role role : user.getRoles()) {
if (role.getArea().equals(user.getActiveArea())) {
for (Permission permission : role.getPermissions()) {
if (permission.getMenuCommandResource() != null &&
permission.getMenuCommandResource().getMenuResourceId() == command.getMenuResourceId()) {
for (Action action : permission.getActions()) {
if (action.getCode().equals(Action.ACTION.VIEW.name()) && action.isActive())
return permission.isActive();
}
}
}
}
}
return false;
}
@Override
public void metadataModuleRegistered(IModuleService source, MetadataModule metadataModule) {
try {
setModuleResource(metadataModule);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void metadataModuleUnregistered(IModuleService source, final MetadataModule metadataModule) {
String id = metadataModule.getId() + "#" + metadataModule.getVersion();
Resource resource = resourceManager.getResource(id);
if (resource != null) {
// remove the bundle tab resource if it's opened
try {
konektiLayout.removeModule(resource.getId());
resource.setTab(null);
} catch (Exception e) {
e.getMessage();
}
// set default command to the bundle menu resource
Command defaultCommand = new Command() {
@Override
public void menuSelected(MenuItem selectedItem) {
window.showNotification("Module Warning",
"The Module: " + metadataModule.getId() + "["
+ metadataModule.getVersion()
+ "] is not deploy",
Window.Notification.TYPE_WARNING_MESSAGE);
}
};
resource.getMenu().setCommand(defaultCommand);
// reset the bundle component resource
resource.setComponentView(null);
}
}
@Override
public void viewChanged(ViewEvent viewEvent) {
if (viewEvent.getViewFrom() instanceof SecurityAccessView) {
SecurityAccessView securityAccessView = (SecurityAccessView) viewEvent.getViewFrom();
try {
User loggedUser = userService.getByUsername(securityAccessView.getGrantedUser().getUsername());
loadWorkbenchContext(loggedUser);
WorkbenchView workbenchView = (WorkbenchView) viewEvent.getViewTo();
workbenchView.setLoggedUser(loggedUser);
menuManager.setUser(loggedUser);
menuManager.setContext(workbenchContext);
// construct the menu from scratch
initMenuManager(loggedUser);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (viewEvent.getViewFrom() instanceof WorkbenchView) {
}
}
private void loadWorkbenchContext(User user) throws Exception {
// create locale for employee agent
String[] localeParams = user.getDefaultLocale().split(LocaleField.LOCALE_SEPARATOR);
String language = localeParams[0];
String country = localeParams[1];
//defaultLocale = new Locale(language, country);
Locale defaultLocale = new Locale(language);
// initialize active Organization tree
user.setActiveOrganization(user.getDefaultOrganization());
user.setActiveLocation(user.getDefaultLocation());
user.setActiveArea(user.getDefaultArea());
user.setActiveLocale(defaultLocale);
// set user Locale
i18n.setCurrentLocale(defaultLocale);
// get all configuratios
List<Configuration> configuration = configurationService.getAll(user);
workbenchContext = new WorkbenchContext(user,
configuration,
menuManager,
toolbarManager,
resourceManager);
}
@Override
public void terminalError(Terminal.ErrorEvent event) {
final Throwable t = event.getThrowable();
if (t instanceof SocketException) {
// Most likely client browser closed socket
logger.info("SocketException in CommunicationManager." + " Most likely client (browser) closed socket.");
return;
}
// show default error view form
ErrorViewForm errorViewForm;
if (t.getCause() != null)
errorViewForm = new ErrorViewForm(t.getCause().getMessage(), t.getCause().getCause(), getMainWindow());
else
errorViewForm = new ErrorViewForm(null, null, getMainWindow());
errorViewForm.show();
// also print the error on console
logger.log(Level.SEVERE, "Terminal error:", t);
}
@Override
public void userChangedButtonClick(User user) {
// set konekti locale
i18n.setCurrentLocale(user.getActiveLocale());
// remove all module tabs from workbech an all panels
konektiLayout.removeModules(LOCATION.TOP);
konektiLayout.removeModules(LOCATION.CENTER);
konektiLayout.removeModules(LOCATION.LEFT);
konektiLayout.removeModules(LOCATION.RIGHT);
konektiLayout.removeModules(LOCATION.BOTTON);
// remove all items
konektiLayout.getMenuLayout().removeItems();
// regenerate all items
initMenuManager(user);
}
}