/**
* (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jabylon.updatecenter.repository.ui;
import java.io.Serializable;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import javax.inject.Inject;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import org.jabylon.rest.ui.model.ComputableModel;
import org.jabylon.rest.ui.security.RestrictedComponent;
import org.jabylon.rest.ui.util.GlobalResources;
import org.jabylon.rest.ui.wicket.BasicPanel;
import org.jabylon.updatecenter.repository.BundleState;
import org.jabylon.updatecenter.repository.OBRRepositoryService;
/**
* @author Johannes Utzig (jutzig.dev@googlemail.com)
*
*/
public class InstalledSoftwareTab extends BasicPanel<String> implements RestrictedComponent{
private static final long serialVersionUID = 1L;
private static final EnumSet<BundleState> STOPPABLE_STATE = EnumSet.of(BundleState.ACTIVE,BundleState.STARTING);
private static final EnumSet<BundleState> STARTABLE_STATE = EnumSet.of(BundleState.RESOLVED);
private static final EnumSet<BundleState> CHANGEABLE_STATE;
static {
EnumSet<BundleState> set = EnumSet.copyOf(STOPPABLE_STATE);
set.addAll(STARTABLE_STATE);
CHANGEABLE_STATE = set;
}
@Inject
private OBRRepositoryService repositoryConnector;
private static final Logger logger = LoggerFactory.getLogger(InstalledSoftwareTab.class);
public InstalledSoftwareTab(String id) {
super(id, Model.of(""),new PageParameters());
final Form<Void> form = new StatelessForm<Void>("form");
add(form);
IModel<List<Bundle>> model = new ComputableModel<Void, List<Bundle>>(new LoadBundlesFunction(), null);
ListView<Bundle> resourceView = new ListView<Bundle>("row", model) {
private static final long serialVersionUID = 1L;
@Override
protected void populateItem(final ListItem<Bundle> item) {
item.setOutputMarkupId(true);
Bundle resource = item.getModelObject();
final long bundleId = resource.getBundleId();
String name = resource.getSymbolicName();
item.add(new Label("name", name));
item.add(new Label("version", resource.getVersion().toString()));
int state = resource.getState();
BundleState bundleState = BundleState.fromState(state);
ComputableModel<Long, String> labelClassModel = new ComputableModel<Long, String>(new ComputeBundleLabelClass(), bundleId);
ComputableModel<Long, String> labelNameModel = new ComputableModel<Long, String>(new ComputeStateFunction(), bundleId);
Label stateLabel = new Label("state",labelNameModel);
stateLabel.add(new AttributeAppender("class", labelClassModel));
item.add(stateLabel);
final String action = bundleState == BundleState.RESOLVED ? "start" : "stop";
//TODO; use AJAX buttons to refresh labels
Button button = new AjaxFallbackButton("action",Model.of(action),form) {
private static final long serialVersionUID = 1L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
if(target!=null)
{
target.add(this);
target.add(item);
}
BundleContext context = FrameworkUtil.getBundle(InstalledSoftwareTab.class).getBundleContext();
Bundle bundle = context.getBundle(bundleId);
BundleState state = BundleState.fromState(bundle.getState());
if(STARTABLE_STATE.contains(state))
{
logger.info("Starting bundle {}", bundle.getSymbolicName());
try {
bundle.start();
} catch (BundleException e) {
String message = "Failed to start bundle "+bundle.getSymbolicName();
getSession().error(message);
logger.error(message,e);
}
}
else if(STOPPABLE_STATE.contains(state)) {
logger.info("Stoping bundle {}", bundle.getSymbolicName());
try {
bundle.stop();
} catch (BundleException e) {
String message = "Failed to stop bundle "+bundle.getSymbolicName();
getSession().error(message);
logger.error(message,e);
}
}
super.onSubmit(target, form);
}
};
button.setDefaultFormProcessing(false);
button.add(new AttributeModifier("value", resource.getBundleId()));
button.add(new AttributeModifier("class", "btn btn-small"));
button.setEnabled(CHANGEABLE_STATE.contains(bundleState));
item.add(button);
}
};
form.add(resourceView);
}
@Override
public void renderHead(IHeaderResponse response) {
response.render(JavaScriptHeaderItem.forReference(GlobalResources.JS_JQUERY_DATATABLES));
response.render(JavaScriptHeaderItem.forReference(GlobalResources.JS_BOOTSTRAP_DATATABLES));
super.renderHead(response);
}
@Override
public String getRequiredPermission() {
return "System:software:config";
}
}
class LoadBundlesFunction implements Function<Void, List<Bundle>>, Serializable {
private static final long serialVersionUID = 1L;
public List<Bundle> apply(Void nothing) {
Bundle bundle = FrameworkUtil.getBundle(getClass());
List<Bundle> resources = Arrays.asList(bundle.getBundleContext().getBundles());
return resources;
}
}
class ComputeStateFunction implements Function<Long, String>, Serializable {
private static final long serialVersionUID = 1L;
public String apply(Long value) {
Bundle bundle = FrameworkUtil.getBundle(getClass());
Bundle target = bundle.getBundleContext().getBundle(value);
return BundleState.fromState(target.getState()).name();
}
}
class ComputeBundleLabelClass implements Function<Long, String>, Serializable {
private static final long serialVersionUID = 1L;
public String apply(Long value) {
Bundle bundle = FrameworkUtil.getBundle(getClass());
Bundle target = bundle.getBundleContext().getBundle(value);
return "label label-"+BundleState.fromState(target.getState()).getLabelClass();
}
}