diff --git a/src/java/net/brutex/xservices/util/BrutexHSQLQuartzConnectionProvider.java b/src/java/net/brutex/xservices/util/BrutexHSQLQuartzConnectionProvider.java new file mode 100644 index 0000000..c959336 --- /dev/null +++ b/src/java/net/brutex/xservices/util/BrutexHSQLQuartzConnectionProvider.java @@ -0,0 +1,181 @@ +/* + * Copyright 2011 Brian Rosenberger (Brutex Network) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.brutex.xservices.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.quartz.utils.ConnectionProvider; + +/** + * @author Brian Rosenberger + * + */ +public class BrutexHSQLQuartzConnectionProvider implements ConnectionProvider { + + private Connection conn = null; + private final Logger logger = Logger.getLogger(this.getClass().getCanonicalName()); + + + public Connection getConnection() throws SQLException { + if( conn!= null && conn.isValid(5)) { + logger.debug("Checking tables on pre-exisiting database connection."); + checkTables(); + return conn; + } + try { + // Class.forName("org.hsqldb.jdbc.JDBCDriver" ); + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + } catch (Exception e) { + logger.fatal("Failed to load Derby JDBC driver."); + e.printStackTrace(); + return null; + } + + if(isConnected(false)) { + checkTables(); + } else { + return null; + } + + return conn; + } + + public void shutdown() throws SQLException { + try { + // Class.forName("org.hsqldb.jdbc.JDBCDriver" ); + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + } catch (Exception e) { + System.err.println("ERROR: failed to load Derby JDBC driver."); + e.printStackTrace(); + return; + } + String t = this.getClass().getClassLoader().getResource("/").toString() + .substring(6); + t += "../data/db"; + System.out.println("Shut down embedded database now."); + Connection c = DriverManager.getConnection("jdbc:derby:" + t + + ";shutdown=true;"); + + } + + private synchronized void recursiveDelete(File dbDir) { + File[] files = dbDir.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].isFile()) { + files[i].delete(); + } else { + recursiveDelete(files[i]); + files[i].delete(); + } + } + dbDir.delete(); + } + + private synchronized void checkTables() throws SQLException { + logger.debug("Checking QUARTZ database schema."); + if(!isConnected(false)) { + logger.error("Failed to validate QUARTZ database schema."); + return; + } + List ddl_list = new ArrayList(11); + ddl_list.add("QRTZ_JOB_DETAILS"); + ddl_list.add("QRTZ_TRIGGERS"); + ddl_list.add("QRTZ_SIMPLE_TRIGGERS"); + ddl_list.add("QRTZ_CRON_TRIGGERS"); + ddl_list.add("QRTZ_SIMPROP_TRIGGERS"); + ddl_list.add("QRTZ_BLOB_TRIGGERS"); + ddl_list.add("QRTZ_CALENDARS"); + ddl_list.add("QRTZ_PAUSED_TRIGGER_GRPS"); + ddl_list.add("QRTZ_FIRED_TRIGGERS"); + ddl_list.add("QRTZ_SCHEDULER_STATE"); + ddl_list.add("QRTZ_LOCKS"); + + String ddl = this.getClass().getClassLoader().getResource("/").toString() + .substring(6)+ "../data/"; + + DatabaseMetaData dmd = conn.getMetaData(); + for (String tbl : ddl_list) { + ResultSet rs = dmd.getTables(null, "APP", tbl, null); + if (!rs.next()) { + logger.log(Level.INFO, "Adding DDL for table "+ tbl); + Statement st = conn.createStatement(); + File ddlFile = new File(ddl + tbl + ".ddl"); + String create = ""; + try { + BufferedReader r = new BufferedReader(new FileReader(ddlFile)); + while (r.ready()) { + create += r.readLine() + "\n"; + } + create.trim(); + if( st.execute(create)) { + logger.log(Level.INFO, "Table " + tbl + " created."); + } + } catch (FileNotFoundException ex) { + ex.printStackTrace(); + } catch (IOException ex) { + ex.printStackTrace(); + } catch (SQLException ex) { + logger.log(Level.ERROR, "Error executing statement "+ create ); + System.out.println(ex.getMessage()); + } + } else { + logger.trace("Table "+tbl+" exists."); + } + } + } + + private synchronized boolean isConnected(boolean fail) throws SQLException { + if(conn!=null && conn.isValid(5)) { + return true; + } else { + String t = this.getClass().getClassLoader().getResource("/").toString().substring(6); // WEB-INF/classes + t += "../data/db"; + logger.debug("Database directory is set to '" + t + "'"); + try { + this.conn = DriverManager.getConnection("jdbc:derby:" + t + ";create=true;"); + } catch (SQLException ex) { + logger.error(ex.getMessage(), ex); + if(!fail) { + logger.warn("Deleting database directory."); + recursiveDelete(new File(t)); + logger.warn("Retrying to connect to database."); + return isConnected(true); + } else { + return false; + } + } + } + return false; + } +} + + diff --git a/src/java/net/brutex/xservices/ws/JobService.java b/src/java/net/brutex/xservices/ws/JobService.java index 2bb4309..11898fe 100644 --- a/src/java/net/brutex/xservices/ws/JobService.java +++ b/src/java/net/brutex/xservices/ws/JobService.java @@ -16,8 +16,6 @@ package net.brutex.xservices.ws; -import java.math.BigInteger; -import java.util.GregorianCalendar; import java.util.List; import javax.jws.WebMethod; @@ -25,13 +23,10 @@ import javax.jws.WebParam; import javax.jws.WebService; import javax.xml.bind.annotation.XmlElement; -import net.brutex.xservices.types.DateFormatType; -import net.brutex.xservices.types.DateTimeUnits; import net.brutex.xservices.types.ScheduledJob; import net.brutex.xservices.util.BrutexNamespaces; import org.apache.cxf.annotations.WSDLDocumentation; -import org.apache.cxf.annotations.WSDLDocumentationCollection; /** * Job management services. diff --git a/src/java/net/brutex/xservices/ws/MiscService.java b/src/java/net/brutex/xservices/ws/MiscService.java index 7b69fd6..3dad615 100644 --- a/src/java/net/brutex/xservices/ws/MiscService.java +++ b/src/java/net/brutex/xservices/ws/MiscService.java @@ -24,6 +24,7 @@ import net.brutex.xservices.types.MailMimeType; import net.brutex.xservices.types.ReturnCode; import net.brutex.xservices.util.BrutexNamespaces; import org.apache.cxf.annotations.WSDLDocumentation; +import org.apache.cxf.annotations.WSDLDocumentationCollection; /** * @@ -31,16 +32,19 @@ import org.apache.cxf.annotations.WSDLDocumentation; * @since 0.4.0 */ @WebService(targetNamespace = BrutexNamespaces.WS_XSERVICES) +@WSDLDocumentation("Various service operations.") public interface MiscService { /** * @param hostname - * @return + * @return ReturnCode */ @WebMethod(operationName = "getHostinfo") - public ReturnCode getHostinfo(@WebParam(name = "hostname") String hostname); + @WSDLDocumentation(value = "Get information about a host.") + public ReturnCode getHostinfo( + @WebParam(name = "hostname") String hostname); /** * @@ -49,9 +53,10 @@ public interface MiscService { * @param tolist * @param subject * @param message - * @return + * @return ReturnCode */ @WebMethod(operationName = "sendMailSimple") + @WSDLDocumentation(value = "Send an email (simple).") public ReturnCode sendMailSimple(@WebParam(name = "mailhost") HostConnection mailhost, @WebParam(name = "from") String from, @WebParam(name = "to") String tolist, @@ -66,9 +71,10 @@ public interface MiscService { * @param subject * @param message * @param res - * @return + * @return ReturnCode */ @WebMethod(operationName = "sendMailSimpleWithAttachment") + @WSDLDocumentation(value = "Send an email with attachment (simple).") public ReturnCode sendMailSimpleWithAttachment(@WebParam(name = "mailhost") HostConnection mailhost, @WebParam(name = "from") String from, @WebParam(name = "to") String tolist, @@ -90,9 +96,10 @@ public interface MiscService { * @param res * @param ssl * @param tls - * @return + * @return ReturnCode */ @WebMethod(operationName = "sendMail") + @WSDLDocumentation(value = "Send an email (advanced).") public ReturnCode sendMail(@WebParam(name = "mailhost") HostConnection mailhost, @WebParam(name = "from") String from, @WebParam(name = "to") String tolist, @@ -110,14 +117,19 @@ public interface MiscService { * * @param minutes * @param seconds - * @return + * @return ReturnCode */ @WebMethod(operationName = "sleep") + @WSDLDocumentation(value = "Delay request response a specified duration.") public ReturnCode sleep(@WebParam(name = "minutes") int minutes, @WebParam(name = "seconds") int seconds); + /** + * @return ReturnCode + */ @WebMethod(operationName = "getInfo") + @WSDLDocumentation(value = "Get XService information.") public ReturnCode getInfo(); } diff --git a/src/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java b/src/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java index 1ffe8cb..4321610 100644 --- a/src/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java +++ b/src/java/net/brutex/xservices/ws/impl/MiscServiceImpl.java @@ -38,10 +38,6 @@ import org.apache.tools.ant.taskdefs.email.EmailTask; * * @author Brian Rosenberger, bru@brutex.de */ -@WSDLDocumentationCollection({ - @WSDLDocumentation("My portType documentation"), - @WSDLDocumentation(value = "My top level documentation", placement = WSDLDocumentation.Placement.TOP), - @WSDLDocumentation(value = "My binding doc", placement = WSDLDocumentation.Placement.BINDING) }) @WebService( targetNamespace = BrutexNamespaces.WS_XSERVICES, endpointInterface = "net.brutex.xservices.ws.MiscService", @@ -49,12 +45,10 @@ import org.apache.tools.ant.taskdefs.email.EmailTask; ) public class MiscServiceImpl implements MiscService { - @WSDLDocumentation(value = "Get information about a host.") public ReturnCode getHostinfo(String hostname) { return antGetHostinfo(hostname, null); } - @WSDLDocumentation(value = "Get XService information.") public ReturnCode getInfo() { ReturnCode r = new ReturnCode(); r.returnCode = 0;