Subversion Repositories XServices

Rev

Rev 201 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
16 brianR 1
/*
114 brianR 2
 *   Copyright 2013 Brian Rosenberger (Brutex Network)
16 brianR 3
 *
4
 *   Licensed under the Apache License, Version 2.0 (the "License");
5
 *   you may not use this file except in compliance with the License.
6
 *   You may obtain a copy of the License at
7
 *
8
 *       http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *   Unless required by applicable law or agreed to in writing, software
11
 *   distributed under the License is distributed on an "AS IS" BASIS,
12
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *   See the License for the specific language governing permissions and
14
 *   limitations under the License.
15
 */
16
 
46 brianR 17
package net.brutex.xservices.ws.impl;
16 brianR 18
 
201 brianR 19
import lombok.extern.slf4j.Slf4j;
199 brianR 20
import net.brutex.xservices.types.*;
21
import net.brutex.xservices.types.alfevent.ALFEventResponseType;
22
import net.brutex.xservices.types.alfevent.ALFEventType;
23
import net.brutex.xservices.types.alfevent.ObjectFactory;
114 brianR 24
import net.brutex.xservices.types.ant.FileSetResource;
199 brianR 25
import net.brutex.xservices.util.EventEmitter;
201 brianR 26
import net.brutex.xservices.util.EventmanagerConfiguration;
17 brianR 27
import net.brutex.xservices.util.RunTask;
46 brianR 28
import net.brutex.xservices.ws.MiscService;
199 brianR 29
import net.brutex.xservices.ws.XServicesFault;
17 brianR 30
import org.apache.tools.ant.taskdefs.HostInfo;
20 brianR 31
import org.apache.tools.ant.taskdefs.Sleep;
18 brianR 32
import org.apache.tools.ant.taskdefs.email.EmailTask;
199 brianR 33
import org.h2.jdbcx.JdbcConnectionPool;
34
import org.quartz.*;
35
import org.quartz.impl.StdSchedulerFactory;
16 brianR 36
 
199 brianR 37
import javax.annotation.Resource;
38
import javax.jws.WebService;
39
import javax.servlet.ServletContext;
40
import javax.xml.bind.JAXBContext;
41
import javax.xml.bind.JAXBElement;
42
import javax.xml.bind.JAXBException;
43
import javax.xml.bind.Marshaller;
203 brianR 44
import javax.xml.namespace.QName;
199 brianR 45
import javax.xml.ws.WebServiceContext;
46
import javax.xml.ws.handler.MessageContext;
47
import java.io.StringReader;
48
import java.io.StringWriter;
49
import java.math.BigInteger;
50
import java.sql.*;
51
import java.time.Instant;
52
import java.util.Date;
53
import java.util.Enumeration;
54
import java.util.Properties;
55
import java.util.UUID;
201 brianR 56
import java.util.concurrent.atomic.AtomicLong;
199 brianR 57
 
58
import static org.quartz.TriggerBuilder.newTrigger;
59
 
60
 
16 brianR 61
/**
114 brianR 62
 * Implements the web service
203 brianR 63
 *
16 brianR 64
 * @author Brian Rosenberger, bru@brutex.de
65
 */
201 brianR 66
@Slf4j
203 brianR 67
@WebService(targetNamespace = "http://ws.xservices.brutex.net", endpointInterface = "net.brutex.xservices.ws.MiscService", serviceName = "MiscService")
114 brianR 68
public class MiscServiceImpl
203 brianR 69
        implements MiscService {
199 brianR 70
 
203 brianR 71
    @Resource
72
    private WebServiceContext context;
73
 
199 brianR 74
    public MiscServiceImpl() throws SchedulerException {
75
    }
76
 
77
    public HostinfoType getHostinfo(String hostname) {
203 brianR 78
        HostInfo info = new HostInfo();
79
        info.setTaskName("HostInfo");
80
        RunTask runner = new RunTask(info);
81
        info.setHost(hostname);
16 brianR 82
 
203 brianR 83
        ReturnCode ret = runner.postTask();
84
        HostinfoType infotype = new HostinfoType(
85
                ret.getProperty("NAME"),
86
                ret.getProperty("DOMAIN"),
87
                ret.getProperty("ADDR4"),
88
                ret.getProperty("ADDR6"));
89
        return infotype;
90
    }
16 brianR 91
 
203 brianR 92
    public ReturnCode getInfo() {
93
        ReturnCode r = new ReturnCode();
94
        r.returnCode = 0;
54 brianR 95
 
203 brianR 96
        Properties props = System.getProperties();
54 brianR 97
 
203 brianR 98
        Enumeration e = props.propertyNames();
99
        while (e.hasMoreElements()) {
100
            String propName = (String) e.nextElement();
54 brianR 101
 
203 brianR 102
            String propValue = (String) props.get(propName);
103
            r.stdOut = (r.stdOut + propName + ": " + propValue + "\n");
104
        }
105
 
106
        return r;
114 brianR 107
    }
97 brianR 108
 
203 brianR 109
    public ReturnCode sendMailSimple(HostConnection mailhost, String from, String tolist, String subject, String message) {
110
        return sendMail(from, from, tolist, "", "", subject, message,
111
                "text/plain", null, mailhost.hostname, mailhost.port,
112
                mailhost.user, mailhost.password, "utf-8", false, false);
113
    }
18 brianR 114
 
203 brianR 115
    public ReturnCode sendMailSimpleWithAttachment(HostConnection mailhost, String from, String tolist, String subject, String message, FileSetResource res) {
116
        return sendMail(from, from, tolist, "", "", subject, message,
117
                "text/plain", res, mailhost.hostname, mailhost.port,
118
                mailhost.user, mailhost.password, "utf-8", false, false);
119
    }
21 brianR 120
 
203 brianR 121
    public ReturnCode sendMail(HostConnection mailhost, String from, String tolist, String cclist, String bcclist, String subject, MailMimeType mimetype, String charset, String message, FileSetResource res, boolean ssl, boolean tls) {
122
        return sendMail(from, from, tolist, cclist, bcclist, subject, message,
123
                mimetype.value(), res, mailhost.hostname, mailhost.port,
124
                mailhost.user, mailhost.password, charset, tls, ssl);
125
    }
21 brianR 126
 
203 brianR 127
    public ReturnCode sleep(int minutes, int seconds) {
128
        return sleep(0, minutes, seconds, 0);
129
    }
21 brianR 130
 
203 brianR 131
    public String generateUUID() {
132
        return UUID.randomUUID().toString();
133
    }
22 brianR 134
 
203 brianR 135
    private ReturnCode sendMail(String from, String replyto, String tolist, String cclist, String bcclist, String subject, String message, String messagemimetype, FileSetResource attachments, String mailhost, int mailport, String user, String password, String charset, boolean tls, boolean ssl) {
136
        EmailTask mail = new EmailTask();
137
        mail.setTaskName("Mail");
138
        RunTask runner = new RunTask(mail);
139
        mail.setFrom(from);
140
        mail.setReplyTo(replyto);
141
        mail.setToList(tolist);
142
        mail.setCcList(cclist);
143
        mail.setBccList(bcclist);
144
        mail.setSubject(subject);
145
        mail.setMessage(message);
146
        mail.setMessageMimeType(messagemimetype);
147
        if (attachments != null) {
148
            mail.addFileset(attachments.getAntResource(mail.getProject()));
149
        }
150
        mail.setMailhost(mailhost);
151
        mail.setMailport(mailport);
152
        mail.setUser(user);
153
        mail.setPassword(password);
154
        mail.setCharset(charset);
155
        mail.setSSL(ssl);
156
        mail.setEnableStartTLS(tls);
157
        return runner.postTask();
158
    }
22 brianR 159
 
203 brianR 160
    private ReturnCode sleep(int hours, int minutes, int seconds, int milliseconds) {
161
        Sleep sleep = new Sleep();
162
        sleep.setTaskName("Sleep");
163
        RunTask runner = new RunTask(sleep);
164
        sleep.setHours(hours);
165
        sleep.setMinutes(minutes);
166
        sleep.setSeconds(seconds);
167
        sleep.setMilliseconds(milliseconds);
168
        return runner.postTask();
114 brianR 169
    }
170
 
203 brianR 171
    public RuntimeInfoType getMemory() {
172
        return new RuntimeInfoType();
173
    }
114 brianR 174
 
203 brianR 175
    @Override
176
    public BigInteger lock(String id, String objectId) throws XServicesFault {
199 brianR 177
 
178
 
203 brianR 179
        final String conString = "jdbc:h2:mem:lockdb;DB_CLOSE_DELAY=10;" +
180
                "INIT=CREATE SCHEMA IF NOT EXISTS brutex\\;" +
181
                // "SET SCHEMA brutex\\;" +
182
                "CREATE SEQUENCE IF NOT EXISTS brutex.btx_sequence1\\;" +
183
                "CREATE TABLE IF NOT EXISTS brutex.tbl_lock (btx_seq BIGINT NOT NULL, btx_id VARCHAR(100) NOT NULL, btx_obj_id VARCHAR(100) NOT NULL, btx_timestamp BIGINT NOT NULL);";
199 brianR 184
 
203 brianR 185
        //JdbcConnectionPool cp = JdbcConnectionPool.create(conString, "sa", "");
186
        //cp.setMaxConnections(1);
199 brianR 187
 
203 brianR 188
        Connection con = null;
189
        long rows = 0L;
190
        final long ts = new Date().getTime();
191
        try {
192
            Class.forName("org.h2.Driver"); //Java 1.8
193
            con = DriverManager.getConnection(conString);
194
            PreparedStatement prep = con.prepareStatement(
195
                    "SELECT btx_id from brutex.tbl_lock where btx_obj_id=? ORDER BY btx_seq DESC");
196
            prep.setString(1, objectId);
199 brianR 197
 
203 brianR 198
            ResultSet rs = prep.executeQuery();
199
            StringBuffer bf = new StringBuffer();
200
            while (rs.next()) {
201
                //bf.append(rs.getString(1));
202
                rows++;
203
            }
204
            rs.close();
199 brianR 205
 
203 brianR 206
            prep = con.prepareStatement("INSERT INTO brutex.tbl_lock values (NEXT VALUE FOR brutex.btx_sequence1, ?, ?, ?)");
207
            prep.setString(1, id);
208
            prep.setString(2, objectId);
209
            prep.setLong(3, ts);
210
            prep.execute();
199 brianR 211
 
203 brianR 212
            prep = con.prepareStatement("DELETE from brutex.tbl_lock WHERE btx_timestamp < ?");
213
            prep.setLong(1, ts - 10000);
214
            prep.execute();
215
            prep.close();
199 brianR 216
 
203 brianR 217
            con.close();
218
            //System.out.println(bf);
219
        } catch (SQLException | ClassNotFoundException e) {
220
            throw new XServicesFault(e);
221
        }
199 brianR 222
 
203 brianR 223
        return BigInteger.valueOf(rows);
199 brianR 224
    }
225
 
203 brianR 226
    @Override
227
    public ALFEventResponseType mergeALFEvent(ALFEventType event) throws XServicesFault {
228
        final Instant d = Instant.now();
229
        final long ts = d.toEpochMilli();
199 brianR 230
 
203 brianR 231
        MessageContext cont = context.getMessageContext();
199 brianR 232
 
203 brianR 233
        //Get Parameters from the Servlet Context
234
        final ServletContext servletContext =
235
                (ServletContext) context.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
236
        final EventmanagerConfiguration conf = (EventmanagerConfiguration) servletContext
237
                .getAttribute(EventmanagerConfiguration.KEY);
201 brianR 238
 
203 brianR 239
        final JdbcConnectionPool pool = (JdbcConnectionPool) servletContext.getAttribute("mdbConnection");
240
        final JdbcConnectionPool fpool = (JdbcConnectionPool) servletContext.getAttribute("fdbConnection");
241
        final AtomicLong egres_counter = (AtomicLong) servletContext.getAttribute("egres_counter");
242
        final AtomicLong ingres_counter = (AtomicLong) servletContext.getAttribute("ingres_counter");
243
        final Scheduler scheduler = (Scheduler) servletContext.getAttribute("scheduler");
201 brianR 244
 
203 brianR 245
        log.trace("Read dbConnection from servlet context: {}", pool);
201 brianR 246
 
203 brianR 247
        //System.out.println("Step 2: " + ChronoUnit.MILLIS.between(Instant.now(), d));
248
        final ObjectFactory of = new ObjectFactory();
199 brianR 249
 
203 brianR 250
        final String objectId = event.getBase().getObjectId();
251
        final String eventId = event.getBase().getEventId();
252
        final String objectType = event.getBase().getObjectType();
253
        final String eventType = event.getBase().getEventType();
254
        log.debug("Event id '{}', type '{}' received for object '{}' with object_id '{}'.",
255
                eventId, eventType, objectType, objectId);
199 brianR 256
 
203 brianR 257
        final String mergeStatememt = "SELECT btx_id FROM OLD TABLE (MERGE INTO brutex.tbl_events " +
258
                "KEY (btx_event_type, btx_obj_type, btx_obj_id) " +
259
                "VALUES (?,?,?,?,?,?));";
199 brianR 260
 
203 brianR 261
        final String insertAll = "INSERT INTO brutex.tbl_events_all VALUES (?,?,?,?,?,?,?)";
201 brianR 262
 
263
 
203 brianR 264
        try (Connection con = pool.getConnection()) {
265
            Marshaller m = JAXBContext.newInstance(ALFEventType.class).createMarshaller();
266
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
267
            m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
268
            m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
269
            JAXBElement<ALFEventType> e = of.createALFEventNoticeDoc(event);
270
            StringWriter sw = new StringWriter();
271
            m.marshal(e, sw);
272
            StringBuilder sb = new StringBuilder();
199 brianR 273
 
203 brianR 274
            sb.append(" <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
275
                    "xmlns:ns=\"http://www.eclipse.org/alf/schema/EventBase/1\">\n");
276
            sb.append("<soapenv:Body>\n");
199 brianR 277
 
203 brianR 278
            sb.append(sw);
199 brianR 279
 
203 brianR 280
            sb.append("</soapenv:Body>");
281
            sb.append("</soapenv:Envelope>");
201 brianR 282
 
199 brianR 283
 
203 brianR 284
            PreparedStatement prep = con.prepareStatement(mergeStatememt);
285
            prep.setString(1, eventType);
286
            prep.setString(2, eventId);
287
            prep.setString(3, objectType);
288
            prep.setString(4, objectId);
289
            prep.setLong(5, ts);
290
            prep.setClob(6, new StringReader(sb.toString()));
291
            ResultSet r = prep.executeQuery();
292
            con.commit();
293
            String supersed_id = null;
294
            if (r.next()) {
295
                supersed_id = r.getString(1);
296
                log.trace("Event '{}' superseded event '{}'", eventId, supersed_id);
297
            } else {
298
                log.trace("Event '{}' inserted into outgoing queue.", eventId);
299
            }
300
 
301
 
302
            /* Write all into permanent storage */
303
            //Connection fcon = fpool.getConnection();
304
            prep = con.prepareStatement(insertAll);
305
            prep.setString(1, eventType);
306
            prep.setString(2, eventId);
307
            prep.setString(3, objectType);
308
            prep.setString(4, objectId);
309
            prep.setLong(5, ts);
310
            prep.setString(6, supersed_id);
311
            prep.setClob(7, new StringReader(sb.toString()));
312
            prep.execute();
313
 
314
            con.commit();
315
            con.close();
316
 
317
            ingres_counter.incrementAndGet();
318
 
319
            if (conf.isEmitterActive()) {
320
                synchronized (scheduler) {
321
                    if (!scheduler.checkExists(JobKey.jobKey("ALFEmitter"))) {
322
                        JobDetail job2 = JobBuilder.newJob(EventEmitter.class)
323
                                .withIdentity("ALFEmitter")
324
                                .build();
325
                        job2.getJobDataMap().put("mdbConnection", pool);
326
                        job2.getJobDataMap().put("fdbConnection", fpool);
327
                        job2.getJobDataMap().put("run_key", ts);
328
                        job2.getJobDataMap().put("egres_counter", egres_counter);
329
                        job2.getJobDataMap().put("ingres_counter", ingres_counter);
330
 
331
                        job2.getJobDataMap().put(EventmanagerConfiguration.KEY, conf);
332
 
333
                        SimpleTrigger t = (SimpleTrigger) newTrigger()
334
                                .withIdentity("ALFEmitter").startAt(Date.from(d.plusSeconds(conf.getInterval())))
335
                                .build();
336
 
337
                        scheduler.scheduleJob(job2, t);
338
                    }
339
                }
340
            }
341
        } catch (JAXBException | SQLException | SchedulerException e) {
342
            log.error(e.getMessage());
343
            throw new XServicesFault(e);
344
        }
345
        return of.createALFEventResponseType();
199 brianR 346
    }
114 brianR 347
}