Java tutorial
/** * This file is part of JEMMA - http://jemma.energy-home.org * (C) Copyright 2013 Telecom Italia (http://www.telecomitalia.it) * * JEMMA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License (LGPL) version 3 * or later as published by the Free Software Foundation, which accompanies * this distribution and is available at http://www.gnu.org/licenses/lgpl.html * * JEMMA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License (LGPL) for more details. * */ package org.energy_home.jemma.hac.adapter.http; import org.energy_home.jemma.ah.hac.IAppliance; import org.energy_home.jemma.ah.hac.IAttributeValue; import org.energy_home.jemma.ah.hac.ICategory; import org.energy_home.jemma.ah.hac.ILocation; import org.energy_home.jemma.ah.hac.IServiceCluster; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Dictionary; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.servlet.ServletException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.energy_home.jemma.hac.adapter.http.contexts.UserAdminBasicHttpContext; import org.energy_home.jemma.hac.adapter.http.impl.HacHttpContext; import org.energy_home.jemma.hac.adapter.http.impl.SecureBasicHttpContext; import org.json.JSONArray; import org.json.JSONException; import org.osgi.framework.Bundle; import org.osgi.service.component.ComponentContext; import org.osgi.service.event.Event; import org.osgi.service.event.EventConstants; import org.osgi.service.event.EventHandler; import org.osgi.service.http.HttpContext; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; import org.osgi.service.useradmin.UserAdmin; import edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue; import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue; public class AhHttpAdapter implements EventHandler, HttpServletBinder, HttpImplementor { private static final long serialVersionUID = 1L; int counter = 0; private HttpService httpService = null; private String jsonServletUrl = "/post-json"; private String jsonRpcUrl = "/jsonrpc"; // have to be set to "UserAdminBasicHttpContext" to enable security private String contextType = "UserAdminBasicHttpContext"; private BlockingQueue queue = new LinkedBlockingQueue(); private HttpContext httpContext = null; private JsonRPC jsonRpcServlet; private UserAdmin userAdmin; protected final static Log log = LogFactory.getLog(AhHttpAdapter.class); private CustomJsonServlet customJSONServlet; private HttpImplementor implementor = null; public AhHttpAdapter(HttpImplementor implementor) { this.implementor = implementor; } public AhHttpAdapter(HttpImplementor implementor, String alias) { this.implementor = implementor; String separator = ""; if (!alias.endsWith("/")) { separator = "/"; } this.jsonServletUrl = alias + separator + "post-json"; this.jsonRpcUrl = alias + separator + "jsonrpc"; } public void bind(HttpImplementor implementor) { this.implementor = implementor; } protected void activate(ComponentContext ctxt) { String[] topics = new String[] { "org/telecomitalia/HacEvent/*", }; Dictionary d = new Hashtable(); d.put(EventConstants.EVENT_TOPIC, topics); // d.put(EventConstants.EVENT_FILTER, "(bundle.symbolicName=com.acme.*)" // ); ctxt.getBundleContext().registerService(EventHandler.class.getName(), this, d); Bundle bundle = null; bundle = ctxt.getBundleContext().getBundle(); if (contextType.equals("SecureBasicHttpContext")) { SecureBasicHttpContext c = (SecureBasicHttpContext) httpContext; URL resourceBase = bundle.getEntry(""); URL configFile = bundle.getEntry("jaas_config.txt"); c.setResourceBase(resourceBase); c.setConfigFile(configFile); c.setRealm("Prova!!"); } else if (contextType.equals("UserAdminBasicHttpContext")) { UserAdminBasicHttpContext c = (UserAdminBasicHttpContext) httpContext; c.setUserAdmin(userAdmin); } log.debug("activated"); } protected void deactivate(ComponentContext ctxt) { log.debug("deactivated"); } public synchronized void setUserAdmin(UserAdmin s) { userAdmin = s; if ((contextType.equals("UserAdminBasicHttpContext") && httpContext != null)) { UserAdminBasicHttpContext c = (UserAdminBasicHttpContext) httpContext; c.setUserAdmin(userAdmin); } } public synchronized void setHttpService(HttpService s) { httpService = s; if (contextType.equals("SecureBasicHttpContext")) { httpContext = new SecureBasicHttpContext(null, null, null); } else if (contextType.equals("UserAdminBasicHttpContext")) { httpContext = new UserAdminBasicHttpContext(null, null, null); } else { httpContext = new HacHttpContext(s.createDefaultHttpContext()); } try { jsonRpcServlet = new JsonRPC(this, jsonRpcUrl); customJSONServlet = new CustomJsonServlet(this, jsonServletUrl); httpService.registerServlet(jsonServletUrl, customJSONServlet, null, httpContext); httpService.registerServlet(jsonRpcUrl, jsonRpcServlet, null, httpContext); } catch (ServletException e) { e.printStackTrace(); } catch (NamespaceException e) { e.printStackTrace(); } log.debug("registered http resources"); } public synchronized void unsetHttpService(HttpService s) { if (httpService == s) { try { httpService.unregister(jsonServletUrl); } catch (Exception e) { } try { httpService.unregister(jsonRpcUrl); } catch (Exception e) { } httpService = null; } log.debug("unregistered http resources"); } public Object invokeMethod(Object targetObject, String methodName, ArrayList paramValues) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { int params = paramValues.size(); Method[] methods = targetObject.getClass().getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().compareTo(methodName) == 0) { Class[] paramTypes = method.getParameterTypes(); if (paramTypes.length == params) { // HTTP GET params number matches method param number Object[] arglist = new Object[params]; boolean signatureMach = true; for (int j = 0; j < params; j++) { Class paramT = paramTypes[j]; String typename = paramTypes[j].getName(); /* * currently we support the following param types: * * Enums, int, short, String */ String value = (String) paramValues.get(j).toString(); if (typename.compareTo("int") == 0) { arglist[j] = new Integer(value); } else if (typename.compareTo("java.lang.String") == 0) { arglist[j] = value; } else if (typename.compareTo("short") == 0) { arglist[j] = new Short(value); } else if (typename.compareTo("boolean") == 0) { arglist[j] = new Boolean(value); } else if (typename.compareTo("long") == 0) { arglist[j] = new Long(value); } else if (typename.compareTo("[B") == 0) { // convert value (that is an hex string) into a byte // array byte[] v = hexStringToByteArray(value); arglist[j] = v; } else if (typename.equals("java.util.Vector")) { // checks if the passed value represents a JSON // array if ((value.length() >= 2) && (value.charAt(0) == '[')) { JSONArray outer; try { outer = new JSONArray(value); } catch (JSONException e) { signatureMach = false; break; } // convert the json array into a Vector Vector v = new Vector(); for (int k = 0; k < outer.length(); k++) { try { v.add(outer.get(k)); } catch (JSONException e) { e.printStackTrace(); } } if (v instanceof Vector) { arglist[j] = v; } } } else if (paramT.isInterface()) { Object o = getObjectByPid(value); if (o != null) { arglist[j] = o; } else { signatureMach = false; break; } } else { log.warn("unsupported type '" + typename + "'in target signature"); signatureMach = false; break; } } if (signatureMach) { Object result = null; result = method.invoke(targetObject, arglist); return this.resultToJSON(result); } else { log.error("signature not found for method " + methodName); } } } } throw new RuntimeException("Could not find the method " + methodName + " parameters or name doesn't match"); } public Object getObjectByPid(String pid) { return implementor.getObjectByPid(pid); } public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); } return data; } private String resultToJSON(Object o) { String out = ""; if (o == null) { out = "null"; // legacy with void returning methods in python } else if ((o instanceof List) || (o instanceof Vector)) { out += "[ "; Iterator it = ((List) o).iterator(); boolean first = true; while (it.hasNext()) { if (!first) { out += ", "; } else { first = false; } Object e = it.next(); out += this.resultToJSON(e); } out += " ]"; } else if (o instanceof Enumeration) { out += "[ "; boolean first = true; Enumeration e = (Enumeration) o; while (e.hasMoreElements()) { if (!first) { out += ", "; } else { first = false; } out += this.resultToJSON(e); } out += " ]"; } else if (o instanceof Hashtable) { Hashtable ht = (Hashtable) o; Enumeration keys = ht.keys(); boolean first = true; out = "{ "; while (keys.hasMoreElements()) { if (first) { first = false; } else { out += ", "; } Object key = keys.nextElement(); Object value = ht.get(key); if (value instanceof String) { out += "\"" + key.toString() + "\"" + ": " + "\"" + ht.get(key).toString() + "\""; } else { out += "\"" + key.toString() + "\": " + this.resultToJSON(value); } } out += " }"; } else if (o instanceof String) { // log.debug("traduco " + o); out = "\"" + o.toString() + "\""; } else if (o instanceof Integer) { out = o.toString(); } else if (o instanceof Double) { out = o.toString(); } else if (o instanceof ICategory) { ICategory category = (ICategory) o; out = "{ \"name\": \"" + category.getName() + "\", \"icon\": \"" + category.getIconName() + "\" }"; } else if (o instanceof ILocation) { ILocation location = (ILocation) o; // log.debug("traduco " + location.getName()); out = "{ " + "\"name\": \"" + _(location.getName()) + "\", " + "\"icon\": \"" + location.getIconName() + "\", " + "\"pid\": \"" + location.getPid() + "\"" + "}"; } else if (o instanceof IAppliance) { out += "\"" + ((IAppliance) o).getPid() + "\""; } else if (o instanceof IServiceCluster) { out += "\"" + ((IServiceCluster) o).getEndPoint().getAppliance().getPid() + "\""; } else if (o instanceof IAttributeValue) { IAttributeValue v = (IAttributeValue) o; Object value = v.getValue(); if (value instanceof String) out += "{ \"type\": \"string\", \"value\": " + "\"" + value.toString() + "\" }"; else out += "{ \"type\": \"double\", \"value\": " + value.toString() + " }"; } else if (o instanceof byte[]) { out += "\"" + byteToHex((byte[]) o) + "\""; } else if (o.getClass().isArray()) { Object[] o1 = (Object[]) o; out += "[ "; boolean first = true; for (int i = 0; i < o1.length; i++) { if (!first) { out += ", "; } else { first = false; } out += this.resultToJSON(o1[i]); } out += " ]"; } else { out = "\"" + o.toString() + "\""; } return out; } /** * Translates the passed string * * @param name * @return */ public static String _(String key) { return key; } public void handleEvent(Event event) { if (event.getTopic() == "org/telecomitalia/HacEvent/NEW_APPLIANCE") { try { queue.put(event); } catch (InterruptedException e) { e.printStackTrace(); } } else { log.debug("arrived event " + event.getTopic()); } } /** * method to convert a byte to a hex string. * * @param data * the byte to convert * @return String the converted byte */ private static String byteToHex(byte[] data) { if (data == null) { return ""; } StringBuffer buf = new StringBuffer(); for (int i = 0; i < data.length; i++) { buf.append(toHexChar((data[i] >>> 4) & 0x0F)); buf.append(toHexChar(data[i] & 0x0F)); } return buf.toString(); } /** * Convenience method to convert an int to a hex char. * * @param i * the int to convert * @return char the converted char */ public static char toHexChar(int i) { if ((0 <= i) && (i <= 9)) { return (char) ('0' + i); } else { return (char) ('a' + (i - 10)); } } protected int lastUpdate = 0; protected Vector lastDevicesList = null; public Object getImplementor() { return implementor; } }