| /* |
| * 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; |
| } |
| } |