Command line options are described and added to the client. Registry is modified...
[jabaws.git] / webservices / compbio / ws / server / RegistryWS.java
1 package compbio.ws.server;\r
2 \r
3 import java.io.PrintWriter;\r
4 import java.io.StringWriter;\r
5 import java.io.Writer;\r
6 import java.util.Date;\r
7 import java.util.Map;\r
8 import java.util.Set;\r
9 import java.util.concurrent.ConcurrentHashMap;\r
10 \r
11 import javax.annotation.Resource;\r
12 import javax.jws.WebService;\r
13 import javax.servlet.http.HttpServletRequest;\r
14 import javax.xml.ws.WebServiceContext;\r
15 import javax.xml.ws.handler.MessageContext;\r
16 \r
17 import org.apache.log4j.Logger;\r
18 \r
19 import compbio.data.msa.JABAService;\r
20 import compbio.ws.client.Services;\r
21 import compbio.ws.client.WSTester;\r
22 \r
23 /**\r
24  * JABAWS services registry\r
25  * \r
26  * @author pvtroshin\r
27  * \r
28  */\r
29 @WebService(endpointInterface = "compbio.data.msa.RegistryWS", targetNamespace = "http://msa.data.compbio/01/12/2010/", serviceName = "RegistryWS")\r
30 public class RegistryWS implements compbio.data.msa.RegistryWS, JABAService {\r
31 \r
32         // Ask for resource injection\r
33         @Resource\r
34         WebServiceContext wsContext;\r
35 \r
36         private static Logger log = Logger.getLogger(RegistryWS.class);\r
37 \r
38         /**\r
39          * Stores tested and passed (the test) services and their testing time\r
40          */\r
41         private final static Map<Services, Date> operating = new ConcurrentHashMap<Services, Date>();\r
42 \r
43         /**\r
44          * Indicate whether the services were tested at all\r
45          */\r
46         private static boolean allTested = false;\r
47 \r
48         @Override\r
49         public Set<Services> getSupportedServices() {\r
50                 init();\r
51                 return operating.keySet();\r
52         }\r
53 \r
54         private void init() {\r
55                 // Do not allow tests to run concurrently\r
56                 if (timeToTest()) {\r
57                         synchronized (operating) {\r
58                                 if (timeToTest()) {\r
59                                         testAllServices();\r
60                                         allTested = true;\r
61                                 }\r
62                         }\r
63                 }\r
64         }\r
65 \r
66         private boolean timeToTest() {\r
67                 if (!allTested) {\r
68                         return true;\r
69                 }\r
70                 // 24 h\r
71                 if (getLongestUntestedServiceTime() > 3600 * 24) {\r
72                         return true;\r
73                 }\r
74                 return false;\r
75         }\r
76 \r
77         /**\r
78          * Return time in seconds for the test for the oldest unchecked service\r
79          * \r
80          * @return\r
81          */\r
82         private int getLongestUntestedServiceTime() {\r
83                 int timePassed = 0;\r
84                 for (Services serv : operating.keySet()) {\r
85                         int lasttimepassed = getLastTested(serv);\r
86                         if (timePassed < lasttimepassed) {\r
87                                 timePassed = lasttimepassed;\r
88                         }\r
89                 }\r
90                 return timePassed;\r
91         }\r
92 \r
93         @Override\r
94         public int getLastTested(Services service) {\r
95                 Date testedOn = getLastTestedOn(service);\r
96                 if (testedOn != null) {\r
97                         return (int) ((System.currentTimeMillis() - testedOn.getTime()) / 1000);\r
98                 }\r
99                 return 0;\r
100         }\r
101 \r
102         /**\r
103          * Can potentially return null if the service has not been tested yet.\r
104          */\r
105         @Override\r
106         public Date getLastTestedOn(Services service) {\r
107                 if (operating.containsKey(service)) {\r
108                         return operating.get(service);\r
109                 }\r
110                 return null;\r
111         }\r
112 \r
113         /**\r
114          * TODO improve reporting. stop testing service on unsupported runtime env\r
115          * exception\r
116          */\r
117         @Override\r
118         public String testAllServices() {\r
119                 Writer testlog = new StringWriter();\r
120                 PrintWriter writer = new PrintWriter(testlog, true);\r
121                 WSTester tester = new WSTester(getServicePath(), writer);\r
122                 // This is done deliberately to prevent malicious user from overloading\r
123                 // the server\r
124                 synchronized (operating) {\r
125                         for (Services service : Services.values()) {\r
126                                 if (tester.checkService(service)) {\r
127                                         operating.put(service, new Date());\r
128                                 }\r
129                         }\r
130                 }\r
131                 writer.close();\r
132                 return testlog.toString();\r
133         }\r
134 \r
135         private String getServicePath() {\r
136                 assert wsContext != null : "WS context injection failed!";\r
137                 MessageContext msContext = wsContext.getMessageContext();\r
138                 HttpServletRequest request = (HttpServletRequest) msContext\r
139                                 .get(MessageContext.SERVLET_REQUEST);\r
140 \r
141                 StringBuffer server = request.getRequestURL();\r
142                 server = server.delete(server.lastIndexOf("/"), server.length());\r
143                 return server.toString();\r
144         }\r
145 \r
146         @Override\r
147         public String testService(Services service) {\r
148                 String server = getServicePath();\r
149                 Writer testlog = new StringWriter();\r
150                 PrintWriter writer = new PrintWriter(testlog, true);\r
151                 WSTester tester = new WSTester(server, writer);\r
152                 try {\r
153                         synchronized (operating) {\r
154                                 boolean succeed = tester.checkService(service);\r
155                                 if (succeed) {\r
156                                         operating.put(service, new Date());\r
157                                 }\r
158                         }\r
159                 } finally {\r
160                         writer.close();\r
161                 }\r
162                 return testlog.toString();\r
163         }\r
164 \r
165         @Override\r
166         public boolean isOperating(Services service) {\r
167                 init();\r
168                 return operating.containsKey(service);\r
169         }\r
170 \r
171 }\r