/** * Copyright (C) 2008 - 2014 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * icense version 2 and the aforementioned licenses. * * This program 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 General * Public License for more details. */ package org.n52.ses.startupinit; import static org.apache.http.entity.ContentType.TEXT_XML; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.joda.time.DateTime; import org.joda.time.format.ISODateTimeFormat; import org.n52.oxf.util.web.HttpClient; import org.n52.oxf.util.web.HttpClientException; import org.n52.oxf.util.web.PreemptiveBasicAuthenticationHttpClient; import org.n52.oxf.util.web.SimpleHttpClient; import org.n52.oxf.xmlbeans.tools.XmlUtil; import org.n52.ses.util.common.ConfigurationRegistry; import org.n52.ses.util.common.SESProperties; /** * Servlet class that wakes up the SES after a (re-)start. * */ public class StartupInitServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; private WakeUpThread thread; private String basicAuthUser; private String sesurl; private String basicAuthPassword; @Override public void init() throws ServletException { super.init(); /* * contact the SES to wake it up */ SESProperties parameters = new SESProperties(); InputStream propStream = getServletContext().getResourceAsStream("/WEB-INF/classes/" +ConfigurationRegistry.CONFIG_FILE); try { parameters.load(propStream); } catch (IOException e) { log(e.getMessage(), e); } sesurl = "http://localhost:8080/ses/services/Broker"; try { sesurl = parameters.getProperty(ConfigurationRegistry.SES_INSTANCE).trim(); basicAuthUser = parameters.getProperty(ConfigurationRegistry.BASIC_AUTH_USER); basicAuthPassword = parameters.getProperty(ConfigurationRegistry.BASIC_AUTH_PASSWORD); } catch (Exception e) { /*empty*/ } int time = 1000; try { time = Integer.parseInt(parameters.getProperty(ConfigurationRegistry.TIME_TO_WAKEUP)); } catch (NumberFormatException e) { /*empty*/ } log("##Startup Init Wakeup## contacting "+ sesurl); this.thread = new WakeUpThread(time); this.thread.start(); } @Override public void destroy() { this.thread.setRunning(false); super.destroy(); } public static String getGetCapabilitiesRequest(String sesurl) throws IOException { InputStream capsstream = StartupInitServlet.class.getResourceAsStream( "/sesconfig/wakeup_capabilities_start.xml"); BufferedReader br = new BufferedReader(new InputStreamReader(capsstream)); StringBuilder sb = new StringBuilder(); while (br.ready()) { sb.append(br.readLine()); } br.close(); sb.append(sesurl); capsstream = StartupInitServlet.class.getResourceAsStream( "/sesconfig/wakeup_capabilities_end.xml"); br = new BufferedReader(new InputStreamReader(capsstream)); while (br.ready()) { sb.append(br.readLine()); } br.close(); return sb.toString(); } private class WakeUpThread extends Thread { private boolean running; private int wakeUpTime; private boolean firstRun = true; public WakeUpThread(int time) { this.wakeUpTime = time; this.running = true; this.setName("SES-WakeUp-Thread"); } public void setRunning(boolean running) { this.running = running; } @Override public void run() { int errors = 0; while(this.running && errors < 10) { errors++; try { log("WakeUp Try #"+errors); if (sendWakeUpPost()) { sendWakeUpNotification(); } } catch (IOException e) { log(e.getMessage(), e); } catch (InterruptedException e) { log(e.getMessage(), e); } catch (XmlException e) { log(e.getMessage(), e); } catch (HttpClientException e) { log(e.getMessage(), e); } } } public HttpClient createClient() throws MalformedURLException { PreemptiveBasicAuthenticationHttpClient httpClient = new PreemptiveBasicAuthenticationHttpClient(new SimpleHttpClient()); if (basicAuthUser != null && !basicAuthUser.isEmpty() && basicAuthPassword != null && !basicAuthPassword.isEmpty()) { httpClient.provideAuthentication(new HttpHost(new URL(sesurl).getHost(), new URL(sesurl).getPort()), basicAuthUser, basicAuthPassword); } return httpClient; } private boolean sendWakeUpPost() throws IOException, InterruptedException, XmlException { if (this.firstRun) { Thread.sleep(this.wakeUpTime); this.firstRun = false; } try { Thread.sleep(1000); HttpClient httpClient = createClient(); String payload = getGetCapabilitiesRequest(sesurl); HttpResponse response = httpClient.executePost(sesurl, payload, TEXT_XML); int responseCode = response.getStatusLine().getStatusCode(); if (responseCode >= HttpURLConnection.HTTP_MULT_CHOICE) { return false; } if (response.getEntity() == null) { log("No content! Retry..."); return false; } InputStream contentStream = response.getEntity().getContent(); XmlObject responseContent = XmlObject.Factory.parse(contentStream); XmlObject[] fault = XmlUtil.selectPath("declare namespace soap='http://www.w3.org/2003/05/soap-envelope'; //soap:Fault", responseContent); if (fault != null && fault.length > 0) { log("##Fault received from SES:## "+ responseContent.xmlText()); return false; } log("##Positive response from SES:## "+ responseContent.xmlText()); setRunning(false); return true; } catch (HttpClientException e) { log(Thread.currentThread().getName()+"] Wakeup failed. Retrying... Exception was: " + e.getMessage()); } return false; } private void sendWakeUpNotification() throws HttpClientException, IOException { /* * send an initial wakeup notification -> main resources get initialized */ HttpClient httpClient = createClient(); HttpResponse response = httpClient.executePost(sesurl, readNotification(), TEXT_XML); int responseCode = response.getStatusLine().getStatusCode(); if (responseCode >= HttpURLConnection.HTTP_MULT_CHOICE) { log("Could not send initial notification (HTTP response code "+ responseCode + ")."); } else { log("Succesfully send initial notification."); } } private String readNotification() throws IOException { BufferedReader capsstream = new BufferedReader(new InputStreamReader( StartupInitServlet.class.getResourceAsStream( "/sesconfig/wakeup_notification.xml"))); StringBuilder sb = new StringBuilder(); while (capsstream.ready()) { sb.append(capsstream.readLine()); } capsstream.close(); //send service URL (in <wsa.To> element) return sb.toString().replace("${ses_host}", sesurl). replace("${now}", new DateTime().toString(ISODateTimeFormat.dateTime())); } } }