1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package argos.bangbang.xmlrpc;
32
33 import java.lang.reflect.Method;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41 import javax.management.Notification;
42
43 import org.apache.xmlrpc.XmlRpcException;
44 import org.apache.xmlrpc.XmlRpcHandler;
45 import org.apache.xmlrpc.XmlRpcRequest;
46 import org.mortbay.jetty.servlet.Context;
47 import org.mortbay.jetty.servlet.ServletHolder;
48
49 import argos.annotation.Description;
50 import argos.annotation.Impact;
51 import argos.annotation.Init;
52 import argos.annotation.NotificationHandler;
53 import argos.annotation.RemoveInstrumentation;
54 import argos.annotation.ServiceMeta;
55 import argos.bangbang.jetty6.Jetty;
56 import argos.bangbang.webservice.annotation.WebMethod;
57 import argos.deploy.ComponentManager;
58 import argos.metadata.ComponentMetaInfo;
59 import argos.metadata.ServiceMetaInfo;
60 import argos.naming.NamingService;
61
62
63
64
65
66
67
68 @Description("Adds XML-RPC as a bangbang service to Argos.")
69 public class XmlRpc implements XmlRpcHandler {
70 private static final Logger logger = Logger.getLogger(XmlRpc.class.getName());
71
72 @ServiceMeta public ServiceMetaInfo meta;
73 private Map<String, Method> methodCache;
74 private Map<String, Object> components;
75
76 public XmlRpc() {
77 super();
78 methodCache = new HashMap<String, Method>();
79 components = new HashMap<String, Object>();
80 }
81
82 @Init
83 @Description("Intigrates XML-RPC into Argos.")
84 @Impact(Impact.ACTION)
85 public void init() throws Exception {
86 Jetty jetty = (Jetty) NamingService.getInstance().getComponentByName("!!Jetty6");
87 Context con = new Context(jetty.getJettyServer(), "/xmlrpc");
88 con.addServlet(new ServletHolder(RPCServlet.class), "/*");
89 jetty.addContext(con);
90 }
91
92 @Description("Adds a new component as a webService.")
93 @Impact(Impact.ACTION)
94 public void addComponent(ComponentMetaInfo componentMeta) {
95 Object component = NamingService.getInstance().getComponentByMeta(componentMeta);
96 String name = componentMeta.getName();
97 components.put(name, component);
98
99 for(Method method : component.getClass().getMethods()) {
100 if(method.isAnnotationPresent(WebMethod.class)) {
101 if(methodCache.containsKey(name + "." + method.getName())) {
102 logger.warning("Method " + method.getName() +
103 " already added, ignoring other implementation.");
104 }
105 else {
106 methodCache.put(name + "." + method.getName(), method);
107 logger.info("Adding XML-RPC method " + name + "." + method.getName() + "().");
108 }
109 }
110 }
111 }
112
113 @Description("Removes a component from web services.")
114 @Impact(Impact.ACTION)
115 public void removeComponent(ComponentMetaInfo componentMeta) {
116 String name = componentMeta.getName();
117 components.remove(name);
118 List<String> remove = new ArrayList<String>();
119 for(String key : methodCache.keySet()) {
120 if(key.startsWith(name + ".")) {
121 if(remove.add(key)) {
122 logger.info("Removing XML-RPC method " + key + "().");
123 }
124 }
125 }
126 for(String key : remove) {
127 methodCache.remove(key);
128 }
129 }
130
131 @Description("Invoked for calling the web sevice.")
132 @Impact(Impact.ACTION_INFO)
133 public Object execute(XmlRpcRequest request) throws XmlRpcException {
134 String methodName = request.getMethodName();
135 Object[] params = new Object[request.getParameterCount()];
136 for(int i = 0; i < request.getParameterCount(); i++) {
137 params[i] = request.getParameter(i);
138 }
139
140 Method method = methodCache.get(methodName);
141 if(method == null) {
142 logger.warning("Tried calling " + methodName + "which doesnt exist " +
143 "or isnt exposed with XML-RPC.");
144 throw new XmlRpcException("The method " + methodName + " is not exposed with XML-RPC.");
145 }
146 else {
147 try {
148 return method.invoke(components.get(methodName.substring(0,
149 methodName.indexOf('.'))), params);
150 }
151 catch(Exception e) {
152 logger.log(Level.SEVERE, "Unable to call xml-rpc method " + methodName, e);
153 throw new XmlRpcException("Exception when calling method " + methodName + ": " +
154 e.getMessage(), e);
155 }
156 }
157 }
158
159 @RemoveInstrumentation
160 @NotificationHandler
161 public void handler(Notification not) {
162 if(handle(not)) {
163 ServiceMetaInfo temp = (ServiceMetaInfo) not.getUserData();
164
165 if(temp.dependsOn(meta)) {
166 if(not.getType().equals(ComponentManager.SERVICE_STARTED)) {
167 for(ComponentMetaInfo componentMeta : ((ServiceMetaInfo) not.getUserData()).getComponentMetaInfo()) {
168 addComponent(componentMeta);
169 }
170
171 }
172 else if(not.getType().equals(ComponentManager.SERVICE_STOPPED)) {
173 for(ComponentMetaInfo componentMeta : ((ServiceMetaInfo) not.getUserData()).getComponentMetaInfo()) {
174 removeComponent(componentMeta);
175 }
176 }
177 }
178 }
179 }
180
181 private boolean handle(Notification not) {
182 return (not.getType().equals(ComponentManager.SERVICE_STARTED) ||
183 not.getType().equals(ComponentManager.SERVICE_STOPPED));
184 }
185 }