1 5 package org.h2.server.ftp; 6 7 import java.io.IOException ; 8 import java.io.InputStream ; 9 import java.io.OutputStream ; 10 import java.sql.Connection ; 11 import java.sql.PreparedStatement ; 12 import java.sql.ResultSet ; 13 import java.sql.SQLException ; 14 import java.sql.Statement ; 15 import java.util.ArrayList ; 16 import java.util.HashMap ; 17 18 import org.h2.util.IOUtils; 19 import org.h2.util.JdbcUtils; 20 import org.h2.util.StringUtils; 21 22 public class FileSystemDatabase { 23 private Connection conn; 24 private HashMap preparedMap = new HashMap (); 25 private boolean log; 26 27 FileSystemDatabase(Connection conn, boolean log) throws SQLException { 28 this.conn = conn; 29 this.log = log; 30 Statement stat = conn.createStatement(); 31 conn.setAutoCommit(false); 32 stat.execute("SET ALLOW_LITERALS NONE"); 33 stat.execute("CREATE TABLE IF NOT EXISTS FILES(" + 34 "ID IDENTITY, PARENTID BIGINT, NAME VARCHAR, " + 35 "LASTMODIFIED BIGINT, LENGTH BIGINT, "+ 36 "UNIQUE(PARENTID, NAME))"); 37 stat.execute("CREATE TABLE IF NOT EXISTS FILEDATA(" + 38 "ID BIGINT PRIMARY KEY, DATA BLOB)"); 39 PreparedStatement prep = conn.prepareStatement("SET MAX_LENGTH_INPLACE_LOB ?"); 40 prep.setLong(1, 4096); 41 prep.execute(); 42 commit(); 43 if(log) { 44 ResultSet rs = stat.executeQuery( 45 "SELECT * FROM FILES ORDER BY PARENTID, NAME"); 46 while(rs.next()) { 47 long id = rs.getLong("ID"); 48 long parentId = rs.getLong("PARENTID"); 49 String name = rs.getString("NAME"); 50 long lastModified = rs.getLong("LASTMODIFIED"); 51 long length = rs.getLong("LENGTH"); 52 System.out.println(id + " " + name + " parent:"+parentId+" length:" + length + " lastMod:" + lastModified); 53 } 54 } 55 } 56 57 synchronized void delete(String fullName) { 58 try { 59 long id = getId(fullName, false); 60 PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?"); 61 prep.setLong(1, id); 62 prep.execute(); 63 prep = prepare("DELETE FROM FILEDATA WHERE ID=?"); 64 prep.setLong(1, id); 65 prep.execute(); 66 commit(); 67 } catch(SQLException e) { 68 rollback(); 69 throw convert(e); 70 } 71 } 72 73 synchronized boolean exists(String fullName) { 74 long id = getId(fullName, false); 75 return id >= 0; 76 } 77 78 synchronized void read(String fullName, long skip, OutputStream out) throws IOException { 79 try { 80 long id = getId(fullName, false); 81 PreparedStatement prep = prepare("SELECT DATA FROM FILEDATA WHERE ID=?"); 82 prep.setLong(1, id); 83 ResultSet rs = prep.executeQuery(); 84 if(rs.next()) { 85 InputStream in = rs.getBinaryStream(1); 86 IOUtils.skipFully(in, skip); 87 IOUtils.copyAndClose(in, out); 88 } 89 } catch(SQLException e) { 90 throw convert(e); 91 } 92 } 93 94 synchronized void write(String fullName, InputStream in) throws IOException { 95 try { 96 long id = getId(fullName, false); 97 if(id >= 0) { 98 PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?"); 99 prep.setLong(1, id); 100 prep.execute(); 101 prep = prepare("DELETE FROM FILEDATA WHERE ID=?"); 102 prep.setLong(1, id); 103 prep.execute(); 104 } 105 long parentId = getId(fullName, true); 106 PreparedStatement prep = prepare("INSERT INTO FILES(PARENTID, NAME, LASTMODIFIED) VALUES(?, ?, ?)"); 107 prep.setLong(1, parentId); 108 prep.setString(2, getName(fullName)); 109 prep.setLong(3, System.currentTimeMillis()); 110 prep.execute(); 111 ResultSet rs = JdbcUtils.getGeneratedKeys(prep); 112 rs.next(); 113 id = rs.getLong(1); 114 prep = prepare("INSERT INTO FILEDATA(ID, DATA) VALUES(?, ?)"); 115 prep.setLong(1, id); 116 prep.setBinaryStream(2, in, -1); 117 in.close(); 118 prep.execute(); 119 prep = prepare("UPDATE FILES SET LENGTH=(SELECT LENGTH(DATA) FROM FILEDATA WHERE ID=?) WHERE ID=?"); 120 prep.setLong(1, id); 121 prep.setLong(2, id); 122 prep.execute(); 123 commit(); 124 } catch(SQLException e) { 125 rollback(); 126 throw convert(e); 127 } 128 } 129 130 synchronized boolean isDirectory(String fullName) { 131 try { 132 long id = getId(fullName, false); 133 PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?"); 134 prep.setLong(1, id); 135 ResultSet rs = prep.executeQuery(); 136 rs.next(); 137 rs.getLong(1); 138 return rs.wasNull(); 139 } catch(SQLException e) { 140 throw convert(e); 141 } 142 } 143 144 synchronized long lastModified(String fullName) { 145 try { 146 long id = getId(fullName, false); 147 PreparedStatement prep = prepare("SELECT LASTMODIFIED FROM FILES WHERE ID=?"); 148 prep.setLong(1, id); 149 ResultSet rs = prep.executeQuery(); 150 rs.next(); 151 return rs.getLong(1); 152 } catch(SQLException e) { 153 throw convert(e); 154 } 155 } 156 157 synchronized long length(String fullName) { 158 try { 159 long id = getId(fullName, false); 160 PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?"); 161 prep.setLong(1, id); 162 ResultSet rs = prep.executeQuery(); 163 rs.next(); 164 return rs.getLong(1); 165 } catch(SQLException e) { 166 throw convert(e); 167 } 168 } 169 170 synchronized FileObject[] listFiles(String fullName) { 171 try { 172 String name = fullName; 173 if(!name.endsWith("/")) { 174 name += "/"; 175 } 176 long id = getId(fullName, false); 177 PreparedStatement prep = prepare("SELECT NAME FROM FILES WHERE PARENTID=? ORDER BY NAME"); 178 prep.setLong(1, id); 179 ResultSet rs = prep.executeQuery(); 180 ArrayList list = new ArrayList (); 181 while(rs.next()) { 182 FileObject f = FileObjectDatabase.get(this, name + rs.getString(1)); 183 list.add(f); 184 } 185 FileObject[] result = new FileObject[list.size()]; 186 list.toArray(result); 187 return result; 188 } catch(SQLException e) { 189 throw convert(e); 190 } 191 } 192 193 String getName(String fullName) { 194 String [] path = StringUtils.arraySplit(fullName, '/', false); 195 return path[path.length-1]; 196 } 197 198 private long getId(String fullName, boolean parent) { 199 try { 200 String [] path = StringUtils.arraySplit(fullName, '/', false); 201 long id = 0; 202 int len = parent ? path.length-1 : path.length; 203 if(fullName.endsWith("/")) { 204 len--; 205 } 206 for(int i=0; i<len; i++) { 207 PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?"); 208 prep.setLong(1, id); 209 prep.setString(2, path[i]); 210 ResultSet rs = prep.executeQuery(); 211 if(!rs.next()) { 212 return -1; 213 } 214 id = rs.getLong(1); 215 } 216 return id; 217 } catch(SQLException e) { 218 throw convert(e); 219 } 220 } 221 222 synchronized void mkdirs(String fullName) { 223 try { 224 String [] path = StringUtils.arraySplit(fullName, '/', false); 225 long parentId = 0; 226 int len = path.length; 227 if(fullName.endsWith("/")) { 228 len--; 229 } 230 for(int i=0; i<len; i++) { 231 PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?"); 232 prep.setLong(1, parentId); 233 prep.setString(2, path[i]); 234 ResultSet rs = prep.executeQuery(); 235 if(!rs.next()) { 236 prep = prepare("INSERT INTO FILES(NAME, PARENTID, LASTMODIFIED) VALUES(?, ?, ?)"); 237 prep.setString(1, path[i]); 238 prep.setLong(2, parentId); 239 prep.setLong(3, System.currentTimeMillis()); 240 prep.execute(); 241 rs = JdbcUtils.getGeneratedKeys(prep); 242 rs.next(); 243 parentId = rs.getLong(1); 244 } else { 245 parentId = rs.getLong(1); 246 } 247 } 248 commit(); 249 } catch(SQLException e) { 250 rollback(); 251 throw convert(e); 252 } 253 } 254 255 synchronized boolean renameTo(String oldFullName, String newFullName) { 256 try { 257 long parentOld = getId(oldFullName, true); 258 long parentNew = getId(newFullName, true); 259 if(parentOld != parentNew) { 260 return false; 261 } 262 String newName = getName(newFullName); 263 long id = getId(oldFullName, false); 264 PreparedStatement prep = prepare("UPDATE FILES SET NAME=? WHERE ID=?"); 265 prep.setString(1, newName); 266 prep.setLong(2, id); 267 prep.execute(); 268 commit(); 269 return true; 270 } catch(SQLException e) { 271 rollback(); 272 throw convert(e); 273 } 274 } 275 276 private RuntimeException convert(SQLException e) { 277 if(log) { 278 e.printStackTrace(); 279 } 280 return new RuntimeException (e.toString()); 281 } 282 283 private PreparedStatement prepare(String sql) throws SQLException { 284 PreparedStatement prep = (PreparedStatement ) preparedMap.get(sql); 285 if(prep == null) { 286 prep = conn.prepareStatement(sql); 287 preparedMap.put(sql, prep); 288 } 289 return prep; 290 } 291 292 private void commit() { 293 try { 294 conn.commit(); 295 } catch(SQLException e) { 296 if(log) { 297 e.printStackTrace(); 298 } 299 } 300 } 301 302 private void rollback() { 303 try { 304 conn.rollback(); 305 } catch(SQLException e) { 306 if(log) { 307 e.printStackTrace(); 308 } 309 } 310 } 311 312 } 313 | Popular Tags |