From b02c8359f983ef85e3a9cdcfc76fdd5f32b27b7c Mon Sep 17 00:00:00 2001 From: Mathew McBride Date: Sun, 18 May 2008 21:48:12 +1000 Subject: [PATCH] Mega experimental fixes; try to stop a new smallsql connection from being opened if one is already present in the VM (unfinished sync session). --- docs/icalsamples/10350.ics | 6 +- docs/icalsamples/10350_1.ics | 4 +- .../java/net/bionicmessage/groupdav/groupDAV.java | 111 +++----- .../MultipleSourceICalendarObjectStore.java | 93 ++++-- ...king.java => MultipleSourceObjectTracking.java} | 313 +++++++++++++-------- .../net/bionicmessage/utils/HTMLFormatter.java | 9 +- .../bionicmessage/utils/JDBCConnectionFactory.java | 67 +++++ .../MultipleSourceICalendarObjectStoreTest.java | 4 +- 8 files changed, 384 insertions(+), 223 deletions(-) rename src/main/java/net/bionicmessage/objects/{ObjectTracking.java => MultipleSourceObjectTracking.java} (61%) mode change 100755 => 100644 create mode 100644 src/main/java/net/bionicmessage/utils/JDBCConnectionFactory.java diff --git a/docs/icalsamples/10350.ics b/docs/icalsamples/10350.ics index 3ec89aa..53e8958 100755 --- a/docs/icalsamples/10350.ics +++ b/docs/icalsamples/10350.ics @@ -7,8 +7,8 @@ CLASS:PUBLIC LOCATION:changed location STATUS:CONFIRMED SUMMARY:Test event -DTEND:20070227T110000Z -DTSTART:20070227T100000Z +DTEND:20080227T110000Z +DTSTART:20080227T100000Z TRANSP:OPAQUE UID:skyrix://ogosync.tietoteema.fi/yritys.template.com/10350 CREATED:20030710T120000Z @@ -19,6 +19,6 @@ X-MICROSOFT-CDO-BUSYSTATUS:BUSY X-MICROSOFT-CDO-INSTTYPE:0 X-MICROSOFT-CDO-ALLDAYEVENT:FALSE ATTENDEE;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;ROLE=OPT-PARTICIPANT;RSVP=FALSE;CN=Mathew McBride:MAILTO:matt@mcbridematt.dhs.org -ORGANIZER;CN=Mathew McBride:MAILTO:matt@mcbridematt.dhs.org + END:VEVENT END:VCALENDAR \ No newline at end of file diff --git a/docs/icalsamples/10350_1.ics b/docs/icalsamples/10350_1.ics index ff63976..bd9b210 100644 --- a/docs/icalsamples/10350_1.ics +++ b/docs/icalsamples/10350_1.ics @@ -6,8 +6,8 @@ BEGIN:VEVENT CLASS:PUBLIC LOCATION:between 11 and 12 SUMMARY:Test event -DTEND:20070227T110000Z -DTSTART:20070227T100000Z +DTEND:20080227T110000Z +DTSTART:20080227T100000Z TRANSP:OPAQUE UID:skyrix://ogosync.tietoteema.fi/yritys.template.com/10350 CREATED:20030710T120000Z diff --git a/src/main/java/net/bionicmessage/groupdav/groupDAV.java b/src/main/java/net/bionicmessage/groupdav/groupDAV.java index 72bf9a4..ee62c8c 100755 --- a/src/main/java/net/bionicmessage/groupdav/groupDAV.java +++ b/src/main/java/net/bionicmessage/groupdav/groupDAV.java @@ -63,6 +63,8 @@ public class groupDAV { private String origurl = ""; private entityFinderHandler storeFinderHandler = null; private entityFinderHandler dirFinderHandler = null; + + private URL serverURL = null; /** For use in situations where something (i.e in the case of * Funambol's authentication) has already given us a HTTP Basic Base64 @@ -76,7 +78,7 @@ public class groupDAV { public groupDAV(String url, String b64cache) { origurl = url; try { - URL serverURL = new URL(url); + serverURL = new URL(url); if (serverURL.getProtocol().contains("https")) { ssl = true; } @@ -110,7 +112,7 @@ public class groupDAV { public groupDAV(String url, String user, String pass) { origurl = url; try { - URL serverURL = new URL(url); + serverURL = new URL(url); if (serverURL.getProtocol().contains("https")) { ssl = true; tok = "https://"; @@ -219,16 +221,25 @@ public class groupDAV { int clength = findContentLength(output); if (clength == -1) { logger.warning("We don't have a Content Length field in listObjects"); - } + /* Temporary, ugly workaround for chunked transfer. Only use if + * you need to + if (output.endsWith("0")) { + int startOfXML = output.indexOf(" -1) { gdir = ""; } String XMLSTRING = "" + - ""; + ""; // String XMLSTRING = ""; String PROPFIND = "PROPFIND " + gdir + subdir + " HTTP/1.1\n" + "Cache-control: no-cache\nPragma: no-cache\nAccept-Language: en\n" + base64cache + "\nContent-Length: " + - XMLSTRING.getBytes().length + "\nHost: " + host + ":" + po + "\n" + + XMLSTRING.getBytes().length + "\nHost: " + host + "\n" + "Depth: 1\nContent-Type: text/xml;charset=utf-8\nAccept: text/*\n\n" + XMLSTRING; return PROPFIND.getBytes(); @@ -388,63 +409,6 @@ public class groupDAV { sparser.parse(new InputSource(new StringReader(xmldata))); } - /** Testing method. Edit source and replace with own - * server settings to test client. */ - public static void main(String args[]) { - /* Todo: use GUI to ask for info */ - String SERVER = "http://your.server.here:80"; - groupDAV client = new groupDAV(SERVER, - "", - ""); - try { - List calobjects = client.listObjects("/groupdav/Calendar/"); - Map etags = client.getEtags(); - for (int i = 0; i < calobjects.size(); i++) { - String objectu = (String) calobjects.get(i); - String eTag = null; - if (etags.get(objectu) != null) { - eTag = (String) etags.get(objectu); - } else { - eTag = "not found"; - } - GroupDAVObject gobj = client.getObject(objectu); - System.err.println(gobj.getContent() + "\n|etag-server=" + eTag); - System.err.println("|etag-object=" + gobj.getEtag()); - String object = gobj.getContent(); - - } - java.util.Random rd = new java.util.Random(); - int uid = rd.nextInt(32); - String u = "" + uid; - String object = "BEGIN:VCALENDAR\n" + - "PRODID:-//BM GroupDAV Client//Test Creation Object/EN\n" + - "VERSION:2.0\n" + - "METHOD:REQUEST\n" + - "BEGIN:VEVENT\n" + - "SUMMARY:Test object\n" + - "LOCATION:In dev slash null\n" + - "DESCRIPTION:Please don't fail me! I'm innocent!\n" + - "DTSTART:20060408T100059Z\n" + - "DTEND:20060408T110059Z\n" + - "TRANSP:OPAQUE\n" + - "UID:" + u + "\n" + - "SEQUENCE:1\n" + - "ORGANIZER:MAILTO:matt@comalies\n" + - "END:VEVENT\n" + - "END:VCALENDAR"; - - // GroupDAVObject gbo = client.postObject(calendarUrl,u,object); - //System.out.println("Etag for new object= " + gbo.getEtag()); - // Test change operation - // object.replaceAll("don't","never"); - // GroupDAVObject gboc = client.modifyObject(gbo.getLocation(),object,gbo.getEtag()); - // GroupDAVObject gbod = client.deleteObject(gbo.getLocation(),gbo.getEtag()); - } catch (Exception ex) { - - ex.printStackTrace(); - } - } - /** Parses the result of PROPFIND */ private class entityFinderHandler extends DefaultHandler { @@ -595,7 +559,12 @@ public class groupDAV { } return -1; } - + /** Sends a request to the server, non-keepalive + * + * @param by A Byte array containing the HTTP request headers and contents + * @return A String of the server result + * @throws java.lang.Exception Due to network error + */ private String sendNonKeepAliveRequest(byte[] by) throws Exception { String dbugstring = new String(by); logger.fine(dbugstring); @@ -675,7 +644,7 @@ public class groupDAV { query += "\nContent-Length: 0"; } - query += "\nUser-Agent: " + USER_AGENT + "\nHost: " + host + ":" + po + + query += "\nUser-Agent: " + USER_AGENT + "\nHost: " + host + "\n\n"; // "Host: " + host + "\n\n\n"; if (contents != null) { diff --git a/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java b/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java index 0ad6aee..faa157b 100644 --- a/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java +++ b/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java @@ -132,19 +132,6 @@ public class MultipleSourceICalendarObjectStore { singlelog = true; } obtrackdir = storedir + File.separatorChar + "obtrack" + File.separatorChar; - if (purgemode) { - File obtrackdirf = new File(obtrackdir); - String[] files = obtrackdirf.list(); - if (obtrackdirf.exists() && files.length > 0) { - for (int i = 0; i < files.length; i++) { - String string = files[i]; - File toDelete = new File(obtrackdir + File.separatorChar + string); - boolean deleted = toDelete.delete(); - System.out.println("Delete " + toDelete.getAbsolutePath() + "..." + deleted); - } - } - obtrackdirf.delete(); - } obtrack = new MultipleSourceObjectTracking(obtrackdir); props = new Properties(); propfile = new File(storedir + File.separatorChar + "vcalstoreprops"); @@ -176,6 +163,7 @@ public class MultipleSourceICalendarObjectStore { } } + /** Loads a list of data sources from the predefinied properties */ public void loadSourcesFromProps() { Iterator listOfProps = props.keySet().iterator(); while (listOfProps.hasNext()) { @@ -227,6 +215,11 @@ public class MultipleSourceICalendarObjectStore { client.setLogger(log); } + /** + * Returns a list of server side data stores discovered by the client + * @return A Hashtable of server side data stores discovered (PROPFIND) by the + * GroupDAV Client + */ public Hashtable getStores() { return client.getURLLocs(); } @@ -252,11 +245,18 @@ public class MultipleSourceICalendarObjectStore { DtStart dts = (DtStart) vcal.getProperty("DTSTART"); DtEnd dte = (DtEnd) vcal.getProperty("DTEND"); java.util.Date dts_date = (java.util.Date) dts.getDate(); - java.util.Date dte_date = (java.util.Date) dte.getDate(); + java.util.Date dte_date = null; + if (dte == null) { // all day event + // TODO: handle as dts_date+24h or dts_date? + dte_date = dts_date; + } else { + dte_date = dte.getDate(); + } dtstart = dts_date.getTime() / 1000; dtend = dte_date.getTime() / 1000; dts = null; - dte = null;; + dte = null; + ; } obtrack.createObject(storeName, uid.getValue(), url, obj.getEtag(), summ.getValue().trim(), obj.getContent(), dtstart, dtend); logList.add(uid.getValue()); @@ -285,6 +285,11 @@ public class MultipleSourceICalendarObjectStore { updatedInStore.add(uid); } + /** + * Deletes an object from the store (not from the server) + * @param uid The object to delete from the store + * @throws java.lang.Exception + */ private void deleteFromStore(String uid) throws Exception { obtrack.deleteObject(uid); deletedFromStore.add(uid); @@ -388,9 +393,17 @@ public class MultipleSourceICalendarObjectStore { return cd; } + /** Starts the synchronisation process. Pulls new and updated + * data from the server and deletes any objects as needed + * @throws java.lang.Exception + */ public void startSync() throws Exception { log.info("Sync started...."); - obtrack.init(); + if (!purgemode) { + obtrack.init(); + } else { + obtrack.initClean(); + } Iterator sourceList = sources.keySet().iterator(); while (sourceList.hasNext()) { String sourceName = sourceList.next(); @@ -432,34 +445,64 @@ public class MultipleSourceICalendarObjectStore { } } + /** Returns a list of UIDs that have not been modified in the last + * sync cycle + * @return An ArrayList of unmodified UIDs + */ public ArrayList getUnModifiedUIDS() { return untouched; } + /** @deprecated */ public ArrayList getAddedToServerUIDS() { return addedToServer; } + /** Returns a list of UIDs that were added(new) from the server in the last + * sync cycle + * @return An ArrayList of new UIDs + */ public ArrayList getAddedToStoreUIDS() { return addedToStore; } + /** Returns a list of UIDs that have been deleted by the user of this sink + * + * @return An ArrayList of UIDs deleted from the server + */ public ArrayList getDeletedFromServerUIDS() { return deletedFromServer; } + /** + * Returns a list of UIDs deleted from the server + * @return An ArrayList of UIDs deleted on the server + */ public ArrayList getDeletedFromStoreUIDS() { return deletedFromStore; } + /** + * Returns a list of UIDs updated on the server + * @return An ArrayList of UIDs updated on the server + */ public ArrayList getUpdatedInStoreUIDS() { return updatedInStore; } + /** + * Returns a list of UIDs modified by us + * @return An ArrayList of UIDs modified by the user + */ public ArrayList getUpdatedOnServerUIDS() { return updatedOnServer; } + /** + * Returns a list of UIDs in the database + * @return An ArrayList of UIDs in the database + * @throws java.sql.SQLException + */ public ArrayList getUIDList() throws SQLException { return obtrack.getUIDList(); } @@ -527,22 +570,27 @@ public class MultipleSourceICalendarObjectStore { log.info(sw.toString()); } + /** Ends this sink session, shuts down the logger and closes the database + * connection + * @throws java.lang.Exception + */ public void close() throws Exception { fh.close(); obtrack.terminate(); } protected void logStart() { - log.info(this.getClass().getName() + " started in "+obtrackdir); - log.info("Purge mode="+purgemode); + log.info(this.getClass().getName() + " started in " + obtrackdir); + log.info("Purge mode=" + purgemode); Iterator it = props.keySet().iterator(); - while(it.hasNext()) { - String prop = (String)it.next(); + while (it.hasNext()) { + String prop = (String) it.next(); String key = props.getProperty(prop); - log.info(prop+"="+key); + log.info(prop + "=" + key); } - + } + public static void main(String[] args) { String storeloc = ""; if (args.length > 0 && args[0] != null) { @@ -560,5 +608,4 @@ public class MultipleSourceICalendarObjectStore { ex.printStackTrace(); } } - } diff --git a/src/main/java/net/bionicmessage/objects/ObjectTracking.java b/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java old mode 100755 new mode 100644 similarity index 61% rename from src/main/java/net/bionicmessage/objects/ObjectTracking.java rename to src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java index 1a75021..42d3fed --- a/src/main/java/net/bionicmessage/objects/ObjectTracking.java +++ b/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java @@ -1,8 +1,8 @@ /* - * ObjectTracking.java + * MultipleSourceObjectTracking.java * - * Created on 26 August 2006, 13:24 - * Copyright (c) 2006 Mathew McBride / "BionicMessage.net" + * Original file created on 26 August 2006, 13:24 + * Copyright (c) 2006-2008 Mathew McBride / "BionicMessage.net" * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -19,17 +19,23 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. - * + * */ package net.bionicmessage.objects; + +import java.io.File; +import java.io.IOException; import java.sql.*; import java.util.ArrayList; import net.bionicmessage.extutils.Base64; +import net.bionicmessage.utils.JDBCConnectionFactory; + /** * - * @author matt + * @ObjMultipleSourceObjectTracking */ -public class ObjectTracking { +public class MultipleSourceObjectTracking { + private String dbpath = ""; private Connection conn = null; private String dburl = ""; @@ -40,19 +46,66 @@ public class ObjectTracking { private static final String URLLIST = "urllist"; private static final String DATELIST = "datelist"; private static final String NOTWANTLIST = "notwanted"; - /** Creates a new instance of ObjectTracking */ - public ObjectTracking(String dbpath) { + private JDBCConnectionFactory jdbcFactory = null; + + /** Creates a newObjMultipleSourceObjectTrackingjectTracking */ + public MultipleSourceObjectTracking(String dbpath) { this.dbpath = dbpath; - dburl = "jdbc:smallsql:"+dbpath+"?create=true"; + dburl = "jdbc:smallsql:" + dbpath + "?create=true"; + jdbcFactory = JDBCConnectionFactory.getInstance(); } + public void terminate() throws SQLException { conn.close(); + JDBCConnectionFactory.removeConnection(dburl); } + public void init() throws Exception { - Class.forName( "smallsql.database.SSDriver" ); - conn = java.sql.DriverManager.getConnection(dburl); + Class.forName("smallsql.database.SSDriver"); + //conn = java.sql.DriverManager.getConnection(dburl); + if (jdbcFactory.doesConnectionExist(dburl)) { + initClean(); + } else { + conn = jdbcFactory.getConnection(dburl); + if (conn == null) { + throw new Exception("Critical error: No SmallSQL connection. DBURL:" + dburl); + } + createTablesIfNeeded(); + } + } + + /** Function designed for Funambol slow syncs. If an errored instance exists + * in the VM, close its connection, purge, and then make ours. + * @throws java.sql.SQLException + * @throws java.io.IOException + */ + public void initClean() throws SQLException, IOException, ClassNotFoundException { + Class.forName("smallsql.database.SSDriver"); + if (JDBCConnectionFactory.doesConnectionExist(dburl)) { + conn = JDBCConnectionFactory.getConnection(dburl); + terminate(); + } + File dbDir = new File(dbpath); + if (dbDir.exists()) { + String[] files = dbDir.list(); + if (dbDir.exists() && files.length > 0) { + for (int i = 0; i < files.length; i++) { + String string = files[i]; + File toDelete = new File(dbDir, string); + boolean deleted = toDelete.delete(); + System.out.println("Delete " + toDelete.getAbsolutePath() + "..." + deleted); + } + } + boolean deleted = dbDir.delete(); + int one = 2; + } + conn = JDBCConnectionFactory.getConnection(dburl); + if (conn == null) { + throw new SQLException("Critical error: No SmallSQL connection. DBURL:" + dburl); + } createTablesIfNeeded(); } + public void createTablesIfNeeded() throws SQLException { boolean create = false; try { @@ -70,9 +123,10 @@ public class ObjectTracking { executeSQL(CREATE_NOTWANTED); } } - + /** * Adds an object to the store + * @param sourceName The server source for that object * @param uid The UID for the object * @param url The URL from which the server copy of the object can be * obtained from @@ -83,78 +137,88 @@ public class ObjectTracking { * @param dtend The Unix time at which this object ends * @throws java.sql.SQLException Thrown when the store encounters a problem adding an object to the database */ - public void createObject(String uid, + public void createObject(String sourceName, + String uid, String url, String etag, String name, String contents, long dtstart, long dtend) throws SQLException { - String newuid = "INSERT INTO " + OBJLIST + "(\"obj_uid\") VALUES ('"+uid+"')"; + String newuid = String.format("INSERT INTO %s (\"obj_source\", \"obj_uid\") VALUES ('%s','%s')", + OBJLIST, sourceName, uid); executeSQL(newuid); - String newurl = "INSERT INTO " + URLLIST + "(\"obj_uid\",\"obj_url\") VALUES ('"+uid+"','"+url+"')"; + String newurl = String.format("INSERT INTO %s (\"obj_source\", \"obj_uid\",\"obj_url\") VALUES ('%s','%s','%s')", + URLLIST, sourceName, uid, url); executeSQL(newurl); - String newetag = "INSERT INTO " + ETAGLIST + "(\"obj_uid\",\"obj_etag\") VALUES ('"+uid+"','"+etag+"')"; + String newetag = "INSERT INTO " + ETAGLIST + "(\"obj_uid\",\"obj_etag\") VALUES ('" + uid + "','" + etag + "')"; executeSQL(newetag); - name = name.replace("'","\""); - String newname = "INSERT INTO " + NAMELIST + "(\"obj_uid\",\"obj_name\") VALUES ('"+uid+"','"+name+"')"; + name = name.replace("'", "\""); + String newname = "INSERT INTO " + NAMELIST + "(\"obj_uid\",\"obj_name\") VALUES ('" + uid + "','" + name + "')"; executeSQL(newname); String newobject = "INSERT INTO " + OBJECTS + "(\"obj_uid\",\"obj_contents\") VALUES (?,?)"; PreparedStatement innewobject = conn.prepareStatement(newobject); innewobject.setString(1, uid); innewobject.setBytes(2, contents.getBytes()); innewobject.execute(); - String insertdates = "INSERT INTO " + DATELIST + "(\"obj_uid\",\"obj_dtstart\",\"obj_dtend\") VALUES ('"+uid+"','"+dtstart+"','"+dtend+"')"; + String insertdates = "INSERT INTO " + DATELIST + "(\"obj_uid\",\"obj_dtstart\",\"obj_dtend\") VALUES ('" + uid + "','" + dtstart + "','" + dtend + "')"; executeSQL(insertdates); } + public void deleteObject(String uid) throws SQLException { - String deleteuid = "DELETE FROM " + OBJLIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteuid = "DELETE FROM " + OBJLIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteuid); - String deleteetag = "DELETE FROM " + ETAGLIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteetag = "DELETE FROM " + ETAGLIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteetag); - String deletename = "DELETE FROM " + NAMELIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deletename = "DELETE FROM " + NAMELIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deletename); - String deleteobject= "DELETE FROM " + OBJECTS + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteobject = "DELETE FROM " + OBJECTS + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteobject); - String deleteurl = "DELETE FROM " + URLLIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteurl = "DELETE FROM " + URLLIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteurl); - String deletedate = "DELETE FROM " + DATELIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deletedate = "DELETE FROM " + DATELIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deletedate); } + public boolean doesUidMatchTimes(String uid, long dstime, long detime) throws SQLException { - String findDate = String.format("SELECT \"obj_uid\" FROM \"%s\" WHERE \"obj_uid\" = '%s' AND \"obj_dtstart\" = %d AND \"obj_dtend\" = %d", DATELIST, uid, dstime, detime ); + String findDate = String.format("SELECT \"obj_uid\" FROM \"%s\" WHERE \"obj_uid\" = '%s' AND \"obj_dtstart\" = %d AND \"obj_dtend\" = %d", DATELIST, uid, dstime, detime); String result = get1x1SQL(findDate); - if (result != null) + if (result != null) { return true; + } return false; } + public String findObjectByURL(String url) throws SQLException { - String findUid = "SELECT \"obj_uid\" FROM \"" + URLLIST + "\" WHERE \"obj_url\" = '" + url +"'"; + String findUid = "SELECT \"obj_uid\" FROM \"" + URLLIST + "\" WHERE \"obj_url\" = '" + url + "'"; String result = get1x1SQL(findUid); return result; } + public String findObjectByName(String name) throws SQLException { - name = name.replace("'","\""); - String findUid = "SELECT \"obj_uid\" FROM \"" + NAMELIST + "\" WHERE \"obj_name\" = '" + name +"'"; + name = name.replace("'", "\""); + String findUid = "SELECT \"obj_uid\" FROM \"" + NAMELIST + "\" WHERE \"obj_name\" = '" + name + "'"; String result = get1x1SQL(findUid); return result; } + public ArrayList findObjectsByName(String name) throws SQLException { ArrayList results = new ArrayList(); - name = name.replace("'","\""); - String findUid = "SELECT \"obj_uid\" FROM \"" + NAMELIST + "\" WHERE \"obj_name\" = '" + name +"'"; + name = name.replace("'", "\""); + String findUid = "SELECT \"obj_uid\" FROM \"" + NAMELIST + "\" WHERE \"obj_name\" = '" + name + "'"; String result = get1x1SQL(findUid); Statement stmt = conn.createStatement(); stmt.execute(findUid); ResultSet rs = stmt.getResultSet(); - while(rs.next()) { + while (rs.next()) { String id = rs.getString("obj_uid"); results.add(id); } return results; } + public String getObjectContents(String uid) throws SQLException { - String findObject = "SELECT \"obj_contents\" FROM \"" + OBJECTS + "\" WHERE \"obj_uid\" = '"+uid+"'"; + String findObject = "SELECT \"obj_contents\" FROM \"" + OBJECTS + "\" WHERE \"obj_uid\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findObject); ResultSet rs = stmt.getResultSet(); @@ -165,94 +229,115 @@ public class ObjectTracking { String cn = new String(rs.getBytes("obj_contents")); return cn; } + public String getObjectEtag(String uid) throws SQLException { - String findObject = "SELECT \"obj_etag\" FROM \"" + ETAGLIST + "\" WHERE \"obj_uid\" = '"+uid+"'"; - String result = get1x1SQL(findObject);; + String findObject = "SELECT obj_etag FROM " + ETAGLIST + " WHERE obj_uid = '" + uid + "'"; + String result = get1x1SQL(findObject); + ; return result; } + public String getObjectName(String uid) throws SQLException { - String findObject = "SELECT \"obj_name\" FROM \"" + NAMELIST + "\" WHERE \"obj_uid\" = '"+uid+"'"; - String result = get1x1SQL(findObject);; + String findObject = "SELECT \"obj_name\" FROM \"" + NAMELIST + "\" WHERE \"obj_uid\" = '" + uid + "'"; + String result = get1x1SQL(findObject); + ; return result; } + public String getObjectURL(String uid) throws SQLException { - String findObject = "SELECT \"obj_url\" FROM \"" + URLLIST + "\" WHERE \"obj_uid\" = '"+uid+"'"; - String result = get1x1SQL(findObject);; + String findObject = "SELECT \"obj_url\" FROM \"" + URLLIST + "\" WHERE \"obj_uid\" = '" + uid + "'"; + String result = get1x1SQL(findObject); return result; } + + public String getObjectSource(String uid) throws SQLException { + String findObject = String.format("SELECT \"obj_uid\" FROM %s WHERE \"obj_uid\" = '%s'", OBJLIST, uid); + String result = get1x1SQL(findObject); + return result; + } + public void updateEtag(String uid, String etag) throws SQLException { - String deleteetag = "DELETE FROM " + ETAGLIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteetag = "DELETE FROM " + ETAGLIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteetag); - String newetag = "INSERT INTO " + ETAGLIST + "(\"obj_uid\",\"obj_etag\") VALUES ('"+uid+"','"+etag+"')"; + String newetag = "INSERT INTO " + ETAGLIST + "(\"obj_uid\",\"obj_etag\") VALUES ('" + uid + "','" + etag + "')"; executeSQL(newetag); } + public void updateName(String uid, String name) throws SQLException { - name = name.replace("'","\""); - String deletename = "DELETE FROM " + NAMELIST + " WHERE \"obj_uid\" = '"+uid+"'"; + name = name.replace("'", "\""); + String deletename = "DELETE FROM " + NAMELIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deletename); - String newname = "INSERT INTO " + NAMELIST + "(\"obj_uid\",\"obj_name\") VALUES ('"+uid+"','"+name+"')"; + String newname = "INSERT INTO " + NAMELIST + "(\"obj_uid\",\"obj_name\") VALUES ('" + uid + "','" + name + "')"; executeSQL(newname); } + public void updateObject(String uid, String content) throws SQLException { - String deleteobject= "DELETE FROM " + OBJECTS + " WHERE \"obj_uid\" = '"+uid+"'"; + String deleteobject = "DELETE FROM " + OBJECTS + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deleteobject); String objectBase64 = Base64.encodeBytes(content.getBytes()); String newobject = "INSERT INTO " + OBJECTS + "(\"obj_uid\",\"obj_contents\") VALUES (?,?)"; PreparedStatement innewobject = conn.prepareStatement(newobject); innewobject.setString(1, uid); innewobject.setBytes(2, content.getBytes()); - innewobject.execute(); + boolean executed = innewobject.execute(); } + public void updateDate(String uid, long dtstart, long dtend) throws SQLException { - String deletedate = "DELETE FROM " + DATELIST + " WHERE \"obj_uid\" = '"+uid+"'"; + String deletedate = "DELETE FROM " + DATELIST + " WHERE \"obj_uid\" = '" + uid + "'"; executeSQL(deletedate); - String newdate = "INSERT INTO " + DATELIST + "(\"obj_uid\",\"obj_dtstart\",\"obj_dtend\") VALUES ('"+uid+"',"+dtstart+","+dtend+")"; + String newdate = "INSERT INTO " + DATELIST + "(\"obj_uid\",\"obj_dtstart\",\"obj_dtend\") VALUES ('" + uid + "'," + dtstart + "," + dtend + ")"; executeSQL(newdate); } + public boolean doesObjectExist(String uid) throws SQLException { - String findObject = "SELECT \"obj_uid\" FROM \"" + OBJLIST + "\" WHERE \"obj_uid\" = '"+uid+"'"; + String findObject = "SELECT \"obj_uid\" FROM \"" + OBJLIST + "\" WHERE \"obj_uid\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findObject); ResultSet rs = stmt.getResultSet(); return rs.next(); } + public boolean doesURLExist(String url) throws SQLException { - String findObject = "SELECT \"obj_url\" FROM \"" + URLLIST + "\" WHERE \"obj_url\" = '"+url+"'"; + String findObject = "SELECT \"obj_url\" FROM \"" + URLLIST + "\" WHERE \"obj_url\" = '" + url + "'"; Statement stmt = conn.createStatement(); stmt.execute(findObject); ResultSet rs = stmt.getResultSet(); return rs.next(); } + public boolean doesObjectApplyAtTime(String uid, int time) throws SQLException { - String findObject = "SELECT \"obj_uid\" FROM \"" + DATELIST + "\" WHERE \"obj_uid\" = '"+ uid +"' AND WHERE \"obj_dtstart\" <= " + time + " AND \"obj_dtend\" >= " + time; + String findObject = "SELECT \"obj_uid\" FROM \"" + DATELIST + "\" WHERE \"obj_uid\" = '" + uid + "' AND WHERE \"obj_dtstart\" <= " + time + " AND \"obj_dtend\" >= " + time; Statement stmt = conn.createStatement(); stmt.execute(findObject); ResultSet rs = stmt.getResultSet(); return rs.next(); } + public long getDtStartForUid(String uid) throws SQLException { - String findUid = "SELECT \"obj_dtstart\" FROM \""+ DATELIST + "\" WHERE \"obj_uid\" = '" + uid +"'"; + String findUid = "SELECT \"obj_dtstart\" FROM \"" + DATELIST + "\" WHERE \"obj_uid\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findUid); ResultSet rs = stmt.getResultSet(); rs.next(); return rs.getLong("obj_dtstart"); } + public long getDtEndFromUid(String uid) throws SQLException { - String findUid = "SELECT \"obj_dtend\" FROM \""+ DATELIST + "\" WHERE \"obj_uid\" = '" + uid +"'"; + String findUid = "SELECT \"obj_dtend\" FROM \"" + DATELIST + "\" WHERE \"obj_uid\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findUid); ResultSet rs = stmt.getResultSet(); rs.next(); return rs.getLong("obj_dtend"); } + public ArrayList getUIDList() throws SQLException { String uidList = "SELECT \"obj_uid\" FROM \"" + OBJLIST + "\""; Statement stmt = conn.createStatement(); stmt.execute(uidList); ResultSet rs = stmt.getResultSet(); ArrayList uidlist = new ArrayList(); - while(rs.next()) { + while (rs.next()) { String uid = rs.getString("obj_uid"); uidlist.add(uid); } @@ -260,13 +345,29 @@ public class ObjectTracking { rs = null; return uidlist; } + public ArrayList getURLList() throws SQLException { - String urlList = "SELECT \"obj_url\" FROM \"" + URLLIST+ "\""; + String urlList = "SELECT \"obj_url\" FROM \"" + URLLIST + "\""; + Statement stmt = conn.createStatement(); + stmt.execute(urlList); + ResultSet rs = stmt.getResultSet(); + ArrayList urllist = new ArrayList(); + while (rs.next()) { + String url = rs.getString("obj_url"); + urllist.add(url); + } + stmt = null; + rs = null; + return urllist; + } + + public ArrayList getURLListForSource(String sourceName) throws SQLException { + String urlList = String.format("SELECT \"obj_url\" FROM %s WHERE \"obj_source\" = '%s'", URLLIST, sourceName); Statement stmt = conn.createStatement(); stmt.execute(urlList); ResultSet rs = stmt.getResultSet(); ArrayList urllist = new ArrayList(); - while(rs.next()) { + while (rs.next()) { String url = rs.getString("obj_url"); urllist.add(url); } @@ -274,17 +375,19 @@ public class ObjectTracking { rs = null; return urllist; } - public void addForgottenURL(String url,String etag) throws SQLException { - String newurl = "INSERT INTO " + NOTWANTLIST + "(\"obj_url\",\"obj_etag\") VALUES ('"+url+"','"+etag+"')"; + + public void addForgottenURL(String url, String etag) throws SQLException { + String newurl = "INSERT INTO " + NOTWANTLIST + "(\"obj_url\",\"obj_etag\") VALUES ('" + url + "','" + etag + "')"; executeSQL(newurl); } + public ArrayList getForgottenList() throws SQLException { - String urlList = "SELECT \"obj_url\" FROM \"" + NOTWANTLIST+ "\""; + String urlList = "SELECT \"obj_url\" FROM \"" + NOTWANTLIST + "\""; Statement stmt = conn.createStatement(); stmt.execute(urlList); ResultSet rs = stmt.getResultSet(); ArrayList urllist = new ArrayList(); - while(rs.next()) { + while (rs.next()) { String url = rs.getString("obj_url"); urllist.add(url); } @@ -292,28 +395,33 @@ public class ObjectTracking { rs = null; return urllist; } + public void deleteForgottenURL(String url) throws SQLException { - String deleteurl = "DELETE FROM " + NOTWANTLIST + " WHERE \"obj_url\" = '"+url+"'"; + String deleteurl = "DELETE FROM " + NOTWANTLIST + " WHERE \"obj_url\" = '" + url + "'"; executeSQL(deleteurl); } + public boolean isURLForgotten(String url) throws SQLException { - String findObject = "SELECT \"obj_url\" FROM \"" + NOTWANTLIST + "\" WHERE \"obj_url\" = '"+url+"'"; + String findObject = "SELECT \"obj_url\" FROM \"" + NOTWANTLIST + "\" WHERE \"obj_url\" = '" + url + "'"; Statement stmt = conn.createStatement(); stmt.execute(findObject); ResultSet rs = stmt.getResultSet(); return rs.next(); } + public String getEtagForForgottenURL(String url) throws SQLException { - String findObject = "SELECT \"obj_etag\" FROM \"" + NOTWANTLIST + "\" WHERE \"obj_url\" = '"+url+"'"; + String findObject = "SELECT \"obj_etag\" FROM \"" + NOTWANTLIST + "\" WHERE \"obj_url\" = '" + url + "'"; return get1x1SQL(findObject); - + } /* Execute SQL statement which doesn't need ResultSet etc. */ + private void executeSQL(String sql) throws SQLException { Statement stmt = conn.createStatement(); stmt.execute(sql); stmt = null; } + /** * Return a result where there is only one row and one column * @param sql SQL to Execute @@ -330,43 +438,6 @@ public class ObjectTracking { } return rs.getString(1); } - public static void main(String args[]) { - ObjectTracking obtrack = new ObjectTracking("C:\\trackstore"); - try { - obtrack.init(); - obtrack.deleteObject("testobject1"); - obtrack.createObject("testobject1","http://server/groupdav/object","2222","Test event","BEGIN:VCALENDAR\r\nEND:VCALENDAR",1161250627,1161250646); - System.out.println(obtrack.doesObjectExist("testobject1")); - System.out.println(obtrack.doesObjectExist("nonexistent")); - ArrayList uids = obtrack.getUIDList(); - for (int i = 0; i < uids.size(); i++) { - String uid = (String)uids.get(i); - String url = obtrack.getObjectURL(uid); - String etag = obtrack.getObjectEtag(uid); - String name = obtrack.getObjectName(uid); - String data = obtrack.getObjectContents(uid); - long dtstart = obtrack.getDtStartForUid(uid); - long dtend = obtrack.getDtEndFromUid(uid); - System.out.println("----------"); - System.out.println("UID:"+uid); - System.out.println("URL:"+url); - System.out.println("ETAG:"+etag); - System.out.println("NAME:"+name); - System.out.println("DTSTART:"+dtstart); - System.out.println("DTEND:"+dtend); - System.out.println("DATA FOLLOWS:"); - System.out.println(data); - System.out.println("----------"); - } - obtrack.updateEtag("testobject1","4444"); - System.out.println("New etag: "+obtrack.getObjectEtag("testobject1")); - obtrack.updateObject("testobject1","BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nBEGIN:VCALENDAR"); - System.out.println(obtrack.getObjectContents("testobject1")); - obtrack.deleteObject("testobject1"); - } catch (Exception ex) { - ex.printStackTrace(); - } - } public static final String CREATE_ETAG_LIST = "CREATE TABLE etaglist\n" + "(\n" + @@ -374,33 +445,35 @@ public class ObjectTracking { "obj_etag VARCHAR(255) not null\n" + ")"; public static final String CREATE_NAME_LIST = - "CREATE TABLE namelist(\n"+ - "obj_uid VARCHAR(255) not null,\n"+ - "obj_name VARCHAR(255) not null\n"+ + "CREATE TABLE namelist(\n" + + "obj_uid VARCHAR(255) not null,\n" + + "obj_name VARCHAR(255) not null\n" + ")"; public static final String CREATE_OBJECT = - "CREATE TABLE objects(\n"+ - "obj_uid VARCHAR(255) not null,\n"+ - "obj_contents LONGVARBINARY\n"+ + "CREATE TABLE objects(\n" + + "obj_uid VARCHAR(255) not null,\n" + + "obj_contents LONGVARBINARY\n" + ")"; public static final String CREATE_OBJLIST = - "CREATE TABLE objlist(\n"+ - "obj_uid VARCHAR(255) not null\n"+ + "CREATE TABLE objlist(\n" + + "obj_source VARCHAR(255) not null," + + "obj_uid VARCHAR(255) not null" + ")"; public static final String CREATE_URLLIST = - "CREATE TABLE urllist(\n"+ - "obj_uid VARCHAR(255) not null,"+ - "obj_url VARCHAR(2048) not null"+ + "CREATE TABLE urllist(\n" + + "obj_source VARCHAR(255) not null," + + "obj_uid VARCHAR(255) not null," + + "obj_url VARCHAR(2048) not null" + ")"; public static final String CREATE_DATELIST = - "CREATE TABLE datelist(\n"+ - "obj_uid VARCHAR(255) not null,"+ - "obj_dtstart INT not null,"+ - "obj_dtend INT not null"+ + "CREATE TABLE datelist(\n" + + "obj_uid VARCHAR(255) not null," + + "obj_dtstart INT not null," + + "obj_dtend INT not null" + ")"; public static final String CREATE_NOTWANTED = - "CREATE TABLE notwanted(\n"+ - "obj_url VARCHAR(255) not null,"+ - "obj_etag VARCHAR(255) not null"+ + "CREATE TABLE notwanted(\n" + + "obj_url VARCHAR(255) not null," + + "obj_etag VARCHAR(255) not null" + ")"; } diff --git a/src/main/java/net/bionicmessage/utils/HTMLFormatter.java b/src/main/java/net/bionicmessage/utils/HTMLFormatter.java index 02f66b1..0da7905 100755 --- a/src/main/java/net/bionicmessage/utils/HTMLFormatter.java +++ b/src/main/java/net/bionicmessage/utils/HTMLFormatter.java @@ -38,8 +38,8 @@ public class HTMLFormatter extends Formatter { String LASTCLASS = ""; String LASTMETHOD = ""; - /** Creates a new instance of HTMLFormatter */ + /** Creates a new instance of HTMLFormatter */ public HTMLFormatter() { } @@ -48,7 +48,7 @@ public class HTMLFormatter extends Formatter { if (LASTCLASS.equals(record.getSourceClassName())) { records.append("
");
             if (LASTMETHOD.equals(record.getSourceMethodName())) {
-                
+
                 records.append(addMessage(record.getMessage()));
                 if (record.getThrown() != null) {
                     Throwable throwed = record.getThrown();
@@ -68,6 +68,8 @@ public class HTMLFormatter extends Formatter {
             LASTMETHOD = record.getSourceMethodName();
             records.append("

"); records.append(record.getSourceClassName()); + records.append(":"); + records.append(System.currentTimeMillis()); records.append("

"); records.append(addMethodName(record.getSourceMethodName())); records.append("
");
@@ -111,10 +113,13 @@ public class HTMLFormatter extends Formatter {
         }
         return null;
     }
+
     private String addMethodName(String msg) {
         StringBuffer records = new StringBuffer();
         records.append("

"); records.append(msg); + records.append(":"); + records.append(System.currentTimeMillis()); records.append("

"); return records.toString(); } diff --git a/src/main/java/net/bionicmessage/utils/JDBCConnectionFactory.java b/src/main/java/net/bionicmessage/utils/JDBCConnectionFactory.java new file mode 100644 index 0000000..c4d6d3a --- /dev/null +++ b/src/main/java/net/bionicmessage/utils/JDBCConnectionFactory.java @@ -0,0 +1,67 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +package net.bionicmessage.utils; + +import java.util.Hashtable; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * A 'factory' singleton-type thingy that ensures only ONE connection to a JDBC + * resource exists + * @author matt + */ +public class JDBCConnectionFactory { + + private static JDBCConnectionFactory instance = + null; + private static Hashtable connectionTable = null; + + private JDBCConnectionFactory() { + connectionTable = new Hashtable(); + } + + public static JDBCConnectionFactory getInstance() { + if (instance == null) { + return new JDBCConnectionFactory(); + } + return instance; + } + + public static Connection getConnection(String jdbcID) throws SQLException { + if (connectionTable.get(jdbcID) != null) { + return connectionTable.get(jdbcID); + } + // Else, create one + Connection conn = java.sql.DriverManager.getConnection(jdbcID); + connectionTable.put(jdbcID, conn); + return conn; + } + + public static void removeConnection(String jdbcID) { + connectionTable.remove(jdbcID); + } + + public static boolean doesConnectionExist(String jdbcID) { + if (connectionTable.get(jdbcID) != null) { + return true; + } + return false; + } +} diff --git a/src/test/java/MultipleSourceICalendarObjectStoreTest.java b/src/test/java/MultipleSourceICalendarObjectStoreTest.java index 2718509..44f6b91 100644 --- a/src/test/java/MultipleSourceICalendarObjectStoreTest.java +++ b/src/test/java/MultipleSourceICalendarObjectStoreTest.java @@ -98,7 +98,7 @@ public class MultipleSourceICalendarObjectStoreTest { long end = dte.getDate().getTime() / 1000; String uid = ve.getUid().getValue(); String summary = ve.getSummary().getValue(); - uidadded = ico.addObject("two",uid,summary, sample.toString(), start, end); + uidadded = ico.addObject("default",uid,summary, sample.toString(), start, end); ico.printDebugReport(); ico.close(); // Start again @@ -123,7 +123,7 @@ public class MultipleSourceICalendarObjectStoreTest { long end = dte.getDate().getTime() / 1000; String uid = ve.getUid().getValue(); String summary = ve.getSummary().getValue(); - uidadded = ico.addObject("two",uid,summary, sample.toString(), start, end); + uidadded = ico.addObject("default",uid,summary, sample.toString(), start, end); ico.printDebugReport(); ico.close(); // Start up again -- 2.11.4.GIT