blob: dd4b1401bcc6f3708d8fb667693a6ea8642e81f6 [file] [log] [blame]
/*
* Copyright 2009 Marcin.
*
* 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.
* under the License.
*/
package org.apache.karaf.webconsole.admin;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.karaf.admin.AdminService;
import org.apache.karaf.admin.Instance;
import org.apache.karaf.admin.InstanceSettings;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.json.JSONException;
import org.json.JSONWriter;
import org.osgi.framework.BundleContext;
import org.slf4j.LoggerFactory;
/**
* Felix Web Console plugin for interacting with the {@link AdminService}
*/
public class AdminPlugin extends AbstractWebConsolePlugin {
private final org.slf4j.Logger logger = LoggerFactory.getLogger(AdminPlugin.class);
public static final String NAME = "admin";
public static final String LABEL = "Admin";
private String adminJs = "/admin/res/ui/admin.js";
private BundleContext bundleContext;
private AdminService adminService;
private ClassLoader classLoader;
/**
* Blueprint lifecycle callback methods
*/
public void start() {
super.activate(bundleContext);
this.classLoader = this.getClass().getClassLoader();
this.logger.info(LABEL + " plugin activated");
}
public void stop() {
this.logger.info(LABEL + " plugin deactivated");
super.deactivate();
}
@Override
public String getTitle() {
return LABEL;
}
@Override
public String getLabel() {
return NAME;
}
@Override
protected void renderContent(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
final PrintWriter pw = res.getWriter();
String appRoot = (String) req.getAttribute("org.apache.felix.webconsole.internal.servlet.OsgiManager.appRoot");
final String adminScriptTag = "<script src='" + appRoot + this.adminJs + "' language='JavaScript'></script>";
pw.println(adminScriptTag);
pw.println("<script type='text/javascript'>");
pw.println("// <![CDATA[");
pw.println("var imgRoot = '" + appRoot + "/res/imgs';");
pw.println("// ]]>");
pw.println("</script>");
pw.println("<div id='plugin_content'/>");
pw.println("<script type='text/javascript'>");
pw.println("// <![CDATA[");
pw.print("renderAdmin( ");
writeJSON(pw);
pw.println(" )");
pw.println("// ]]>");
pw.println("</script>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
boolean success = false;
String action = req.getParameter("action");
String name = req.getParameter("name");
if (action == null) {
success = true;
} else if ("create".equals(action)) {
int sshPort = parsePortNumber(req.getParameter("sshPort"));
int rmiRegistryPort = parsePortNumber(req.getParameter("rmiRegistryPort"));
int rmiServerPort = parsePortNumber(req.getParameter("rmiServerPort"));
String location = parseString(req.getParameter("location"));
String javaOpts = parseString(req.getParameter("javaOpts"));
List<String> featureURLs = parseStringList(req.getParameter("featureURLs"));
List<String> features = parseStringList(req.getParameter("features"));
InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
success = createInstance(name, settings);
} else if ("destroy".equals(action)) {
success = destroyInstance(name);
} else if ("start".equals(action)) {
String javaOpts = req.getParameter("javaOpts");
success = startInstance(name, javaOpts);
} else if ("stop".equals(action)) {
success = stopInstance(name);
}
if (success) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
this.renderJSON(res, null);
} else {
super.doPost(req, res);
}
}
/*
* Parse the String value, returning <code>null</code> if the String is empty
*/
private String parseString(String value) {
if (value != null && value.trim().length() == 0) {
value = null;
}
return value;
}
private List<String> parseStringList(String value) {
List<String> list = new ArrayList<String>();
if (value != null) {
for (String el : value.split(",")) {
String trimmed = el.trim();
if (trimmed.length() == 0) {
continue;
}
list.add(trimmed);
}
}
return list;
}
/*
* Parse the port number for the String given, returning 0 if the String does not represent an integer
*/
private int parsePortNumber(String port) {
try {
return Integer.parseInt(port);
} catch (NumberFormatException e) {
return 0;
}
}
protected URL getResource(String path) {
path = path.substring(NAME.length() + 1);
URL url = this.classLoader.getResource(path);
if (url != null) {
InputStream ins = null;
try {
ins = url.openStream();
if (ins == null) {
this.logger.error("failed to open " + url);
url = null;
}
} catch (IOException e) {
this.logger.error(e.getMessage(), e);
url = null;
} finally {
if (ins != null) {
try {
ins.close();
} catch (IOException e) {
this.logger.error(e.getMessage(), e);
}
}
}
}
return url;
}
private void renderJSON(final HttpServletResponse response, final String feature) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
final PrintWriter pw = response.getWriter();
writeJSON(pw);
}
private void writeJSON(final PrintWriter pw) {
final JSONWriter jw = new JSONWriter(pw);
final Instance[] instances = adminService.getInstances();
try {
jw.object();
jw.key("status");
jw.value(getStatusLine());
jw.key("instances");
jw.array();
for (Instance i : instances) {
// if (!i.isRoot()) {
instanceInfo(jw, i);
// }
}
jw.endArray();
jw.endObject();
} catch (JSONException ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void instanceInfo(JSONWriter jw, Instance instance) throws JSONException, Exception {
jw.object();
jw.key("pid");
jw.value(instance.getPid());
jw.key("name");
jw.value(instance.getName());
jw.key("sshPort");
jw.value(instance.getSshPort());
jw.key("rmiRegistryPort");
jw.value(instance.getRmiRegistryPort());
jw.key("rmiServerPort");
jw.value(instance.getRmiServerPort());
jw.key("state");
jw.value(instance.getState());
jw.key("location");
jw.value(instance.getJavaOpts() != null ? instance.getJavaOpts() : "");
jw.key("javaopts");
jw.value(instance.getLocation());
jw.key("actions");
jw.array();
action(jw, "destroy", "Destroy", "delete");
if (instance.getState().equals(Instance.STARTED)) {
action(jw, "stop", "Stop", "stop");
} else if (instance.getState().equals(Instance.STARTING)) {
action(jw, "stop", "Stop", "stop");
} else if (instance.getState().equals(Instance.STOPPED)) {
action(jw, "start", "Start", "start");
}
jw.endArray();
jw.endObject();
}
private void action(JSONWriter jw, String op, String title, String image) throws JSONException {
jw.object();
jw.key("op").value(op);
jw.key("title").value(title);
jw.key("image").value(image);
jw.endObject();
}
private String getStatusLine() {
final Instance[] instances = adminService.getInstances();
int started = 0, starting = 0, stopped = 0;
for (Instance instance : instances) {
try {
if (instance.getState().equals(Instance.STARTED)) {
started++;
} else if (instance.getState().equals(Instance.STARTING)) {
starting++;
} else if (instance.getState().equals(Instance.STOPPED)) {
stopped++;
}
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
}
final StringBuffer buffer = new StringBuffer();
buffer.append("Instance information: ");
buffer.append(instances.length);
buffer.append(" instance");
if (instances.length != 1) {
buffer.append('s');
}
buffer.append(" in total");
if (started == instances.length) {
buffer.append(" - all started");
} else {
if (started != 0) {
buffer.append(", ");
buffer.append(started);
buffer.append(" started");
}
if (starting != 0) {
buffer.append(", ");
buffer.append(starting);
buffer.append(" starting");
}
buffer.append('.');
}
return buffer.toString();
}
private boolean createInstance(String name, InstanceSettings settings) {
try {
adminService.createInstance(name, settings);
return true;
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
private boolean destroyInstance(String name) {
try {
Instance instance = adminService.getInstance(name);
if (instance != null) {
instance.destroy();
return true;
}
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
private boolean startInstance(String name, String javaOpts) {
try {
Instance instance = adminService.getInstance(name);
if (instance != null) {
instance.start(javaOpts);
return true;
}
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
private boolean stopInstance(String name) {
try {
Instance instance = adminService.getInstance(name);
if (instance != null) {
instance.stop();
return true;
}
} catch (Exception ex) {
Logger.getLogger(AdminPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
/**
* @param adminService the adminService to set
*/
public void setAdminService(AdminService adminService) {
this.adminService = adminService;
}
/**
* @param bundleContext the bundleContext to set
*/
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
}