|
| 1 | +packageexample; |
| 2 | + |
| 3 | +importjava.awt.*; |
| 4 | +importjava.awt.event.*; |
| 5 | +importjava.io.*; |
| 6 | +importjava.sql.*; |
| 7 | +importpostgresql.largeobject.*; |
| 8 | + |
| 9 | +/** |
| 10 | + * This example is a small application that stores and displays images |
| 11 | + * held on a postgresql database. |
| 12 | + * |
| 13 | + * Before running this application, you need to create a database, and |
| 14 | + * on the first time you run it, select "Initialise" in the "PostgreSQL" |
| 15 | + * menu. |
| 16 | + * |
| 17 | + * Important note: You will notice we import the postgresql.largeobject |
| 18 | + * package, but don't import the postgresql package. The reason for this is |
| 19 | + * that importing postgresql can confuse javac (we have conflicting class names |
| 20 | + * in postgresql.* and java.sql.*). This doesn't cause any problems, as long |
| 21 | + * as no code imports postgresql. |
| 22 | + * |
| 23 | + * Under normal circumstances, code using any jdbc driver only needs to import |
| 24 | + * java.sql, so this isn't a problem. |
| 25 | + * |
| 26 | + * It's only if you use the non jdbc facilities, do you have to take this into |
| 27 | + * account. |
| 28 | + * |
| 29 | + */ |
| 30 | + |
| 31 | +publicclassImageViewerimplementsItemListener |
| 32 | +{ |
| 33 | +Connectiondb; |
| 34 | +Statementstat; |
| 35 | +LargeObjectManagerlom; |
| 36 | +Frameframe; |
| 37 | +Labellabel;// Label used to display the current name |
| 38 | +Listlist;// The list of available images |
| 39 | +imageCanvascanvas;// Canvas used to display the image |
| 40 | +StringcurrentImage;// The current images name |
| 41 | + |
| 42 | +// This is a simple component to display our image |
| 43 | +publicclassimageCanvasextendsCanvas |
| 44 | + { |
| 45 | +privateImageimage; |
| 46 | + |
| 47 | +publicimageCanvas() |
| 48 | + { |
| 49 | +image=null; |
| 50 | + } |
| 51 | + |
| 52 | +publicvoidsetImage(Imageimg) |
| 53 | + { |
| 54 | +image=img; |
| 55 | +repaint(); |
| 56 | + } |
| 57 | + |
| 58 | +// This defines our minimum size |
| 59 | +publicDimensiongetMinimumSize() |
| 60 | + { |
| 61 | +returnnewDimension(400,400); |
| 62 | + } |
| 63 | + |
| 64 | +publicDimensiongetPreferedSize() |
| 65 | + { |
| 66 | +returngetMinimumSize(); |
| 67 | + } |
| 68 | + |
| 69 | +publicvoidupdate(Graphicsg) |
| 70 | + { |
| 71 | +paint(g); |
| 72 | + } |
| 73 | + |
| 74 | +publicvoidpaint(Graphicsg) |
| 75 | + { |
| 76 | +g.setColor(Color.gray); |
| 77 | +g.fillRect(0,0,getSize().width,getSize().height); |
| 78 | + |
| 79 | +if(image!=null) |
| 80 | +g.drawImage(image,0,0,this); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | +publicImageViewer(Framef,Stringurl,Stringuser,Stringpassword)throwsClassNotFoundException,FileNotFoundException,IOException,SQLException |
| 85 | + { |
| 86 | +frame =f; |
| 87 | + |
| 88 | +MenuBarmb =newMenuBar(); |
| 89 | +Menum; |
| 90 | +MenuItemi; |
| 91 | + |
| 92 | +f.setMenuBar(mb); |
| 93 | +mb.add(m =newMenu("PostgreSQL")); |
| 94 | +m.add(i=newMenuItem("Initialise")); |
| 95 | +i.addActionListener(newActionListener() { |
| 96 | +publicvoidactionPerformed(ActionEvente) { |
| 97 | +ImageViewer.this.init(); |
| 98 | + } |
| 99 | + }); |
| 100 | + |
| 101 | +m.add(i=newMenuItem("Exit")); |
| 102 | +ActionListenerexitListener =newActionListener() { |
| 103 | +publicvoidactionPerformed(ActionEvente) { |
| 104 | +ImageViewer.this.close(); |
| 105 | + } |
| 106 | + }; |
| 107 | +m.addActionListener(exitListener); |
| 108 | + |
| 109 | +mb.add(m =newMenu("Image")); |
| 110 | +m.add(i=newMenuItem("Import")); |
| 111 | +ActionListenerimportListener =newActionListener() { |
| 112 | +publicvoidactionPerformed(ActionEvente) { |
| 113 | +ImageViewer.this.importImage(); |
| 114 | + } |
| 115 | + }; |
| 116 | +i.addActionListener(importListener); |
| 117 | + |
| 118 | +m.add(i=newMenuItem("Remove")); |
| 119 | +ActionListenerremoveListener =newActionListener() { |
| 120 | +publicvoidactionPerformed(ActionEvente) { |
| 121 | +ImageViewer.this.removeImage(); |
| 122 | + } |
| 123 | + }; |
| 124 | +i.addActionListener(removeListener); |
| 125 | + |
| 126 | +// To the north is a label used to display the current images name |
| 127 | +f.add("North",label =newLabel()); |
| 128 | + |
| 129 | +// We have a panel to the south of the frame containing the controls |
| 130 | +Panelp =newPanel(); |
| 131 | +p.setLayout(newFlowLayout()); |
| 132 | +Buttonb; |
| 133 | +p.add(b=newButton("Refresh List")); |
| 134 | +b.addActionListener(newActionListener() { |
| 135 | +publicvoidactionPerformed(ActionEvente) { |
| 136 | +ImageViewer.this.refreshList(); |
| 137 | + } |
| 138 | + }); |
| 139 | +p.add(b=newButton("Import new image")); |
| 140 | +b.addActionListener(importListener); |
| 141 | +p.add(b=newButton("Remove image")); |
| 142 | +b.addActionListener(removeListener); |
| 143 | +p.add(b=newButton("Quit")); |
| 144 | +b.addActionListener(exitListener); |
| 145 | +f.add("South",p); |
| 146 | + |
| 147 | +// And a panel to the west containing the list of available images |
| 148 | +f.add("West",list=newList()); |
| 149 | +list.addItemListener(this); |
| 150 | + |
| 151 | +// Finally the centre contains our image |
| 152 | +f.add("Center",canvas =newimageCanvas()); |
| 153 | + |
| 154 | +// Load the driver |
| 155 | +Class.forName("postgresql.Driver"); |
| 156 | + |
| 157 | +// Connect to database |
| 158 | +System.out.println("Connecting to Database URL = " +url); |
| 159 | +db =DriverManager.getConnection(url,user,password); |
| 160 | + |
| 161 | +// Create a statement |
| 162 | +stat =db.createStatement(); |
| 163 | + |
| 164 | +// Also, get the LargeObjectManager for this connection |
| 165 | +lom = ((postgresql.Connection)db).getLargeObjectAPI(); |
| 166 | + |
| 167 | +// Now refresh the image selection list |
| 168 | +refreshList(); |
| 169 | + } |
| 170 | + |
| 171 | + |
| 172 | +/** |
| 173 | + * This method initialises the database by creating a table that contains |
| 174 | + * the image names, and Large Object OID's |
| 175 | + */ |
| 176 | +publicvoidinit() |
| 177 | + { |
| 178 | +try { |
| 179 | +stat.executeUpdate("create table images (imgname name,imgoid oid)"); |
| 180 | +label.setText("Initialised database"); |
| 181 | + }catch(SQLExceptionex) { |
| 182 | +label.setText(ex.toString()); |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | +/** |
| 187 | + * This closes the connection, and ends the application |
| 188 | + */ |
| 189 | +publicvoidclose() |
| 190 | + { |
| 191 | +try { |
| 192 | +db.close(); |
| 193 | + }catch(SQLExceptionex) { |
| 194 | +System.err.println(ex.toString()); |
| 195 | + } |
| 196 | +System.exit(0); |
| 197 | + } |
| 198 | + |
| 199 | +/** |
| 200 | + * This imports an image into the database. |
| 201 | + * |
| 202 | + * This is the most efficient method, using the large object extension. |
| 203 | + */ |
| 204 | +publicvoidimportImage() |
| 205 | + { |
| 206 | +FileDialogd =newFileDialog(frame,"Import Image",FileDialog.LOAD); |
| 207 | +d.setVisible(true); |
| 208 | +Stringname =d.getFile(); |
| 209 | +Stringdir =d.getDirectory(); |
| 210 | +d.dispose(); |
| 211 | + |
| 212 | +// Now the real import stuff |
| 213 | +if(name!=null &&dir!=null) { |
| 214 | +try { |
| 215 | +System.out.println("Importing file"); |
| 216 | +// A temporary buffer - this can be as large as you like |
| 217 | +bytebuf[] =newbyte[2048]; |
| 218 | + |
| 219 | +// Open the file |
| 220 | +System.out.println("Opening file "+dir+"/"+name); |
| 221 | +FileInputStreamfis =newFileInputStream(newFile(dir,name)); |
| 222 | + |
| 223 | +// Gain access to large objects |
| 224 | +System.out.println("Gaining LOAPI"); |
| 225 | + |
| 226 | +// Now create the large object |
| 227 | +System.out.println("creating blob"); |
| 228 | +intoid =lom.create(); |
| 229 | + |
| 230 | +System.out.println("Opening "+oid); |
| 231 | +LargeObjectblob =lom.open(oid); |
| 232 | + |
| 233 | +// Now copy the file into the object. |
| 234 | +// |
| 235 | +// Note: we dont use write(buf), as the last block is rarely the same |
| 236 | +// size as our buffer, so we have to use the amount read. |
| 237 | +System.out.println("Importing file"); |
| 238 | +ints,t=0; |
| 239 | +while((s=fis.read(buf,0,buf.length))>0) { |
| 240 | +System.out.println("Block s="+s+" t="+t);t+=s; |
| 241 | +blob.write(buf,0,s); |
| 242 | +} |
| 243 | + |
| 244 | +// Close the object |
| 245 | +System.out.println("Closing blob"); |
| 246 | +blob.close(); |
| 247 | + |
| 248 | +// Now store the entry into the table |
| 249 | +stat.executeUpdate("insert into images values ('"+name+"',"+oid+")"); |
| 250 | +stat.close(); |
| 251 | + |
| 252 | +// Finally refresh the names list, and display the current image |
| 253 | +refreshList(); |
| 254 | +displayImage(name); |
| 255 | + }catch(Exceptionex) { |
| 256 | +label.setText(ex.toString()); |
| 257 | + } |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | +/** |
| 262 | + * This refreshes the list of available images |
| 263 | + */ |
| 264 | +publicvoidrefreshList() |
| 265 | + { |
| 266 | +try { |
| 267 | +// First, we'll run a query, retrieving all of the image names |
| 268 | +ResultSetrs =stat.executeQuery("select imgname from images order by imgname"); |
| 269 | +if(rs!=null) { |
| 270 | +list.removeAll(); |
| 271 | +while(rs.next()) |
| 272 | +list.addItem(rs.getString(1)); |
| 273 | +rs.close(); |
| 274 | + } |
| 275 | + }catch(SQLExceptionex) { |
| 276 | +label.setText(ex.toString()+" Have you initialised the database?"); |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | +/** |
| 281 | + * This removes an image from the database |
| 282 | + * |
| 283 | + * Note: With postgresql, this is the only way of deleting a large object |
| 284 | + * using Java. |
| 285 | + */ |
| 286 | +publicvoidremoveImage() |
| 287 | + { |
| 288 | +try { |
| 289 | +// Delete any large objects for the current name |
| 290 | +ResultSetrs =stat.executeQuery("select imgoid from images where imgname='"+currentImage+"'"); |
| 291 | +if(rs!=null) { |
| 292 | +// Even though there should only be one image, we still have to |
| 293 | +// cycle through the ResultSet |
| 294 | +while(rs.next()) { |
| 295 | +System.out.println("Got oid "+rs.getInt(1)); |
| 296 | +lom.delete(rs.getInt(1)); |
| 297 | +System.out.println("Import complete"); |
| 298 | +} |
| 299 | + } |
| 300 | +rs.close(); |
| 301 | + |
| 302 | +// Finally delete any entries for that name |
| 303 | +stat.executeUpdate("delete from images where imgname='"+currentImage+"'"); |
| 304 | + |
| 305 | +label.setText(currentImage+" deleted"); |
| 306 | +currentImage=null; |
| 307 | +refreshList(); |
| 308 | + }catch(SQLExceptionex) { |
| 309 | +label.setText(ex.toString()); |
| 310 | + } |
| 311 | + } |
| 312 | + |
| 313 | +/** |
| 314 | + * This displays an image from the database. |
| 315 | + * |
| 316 | + * For images, this is the easiest method. |
| 317 | + */ |
| 318 | +publicvoiddisplayImage(Stringname) |
| 319 | + { |
| 320 | +try { |
| 321 | +System.out.println("Selecting oid for "+name); |
| 322 | +ResultSetrs =stat.executeQuery("select imgoid from images where imgname='"+name+"'"); |
| 323 | +if(rs!=null) { |
| 324 | +// Even though there should only be one image, we still have to |
| 325 | +// cycle through the ResultSet |
| 326 | +while(rs.next()) { |
| 327 | +System.out.println("Got oid "+rs.getInt(1)); |
| 328 | +canvas.setImage(canvas.getToolkit().createImage(rs.getBytes(1))); |
| 329 | +System.out.println("Import complete"); |
| 330 | +label.setText(currentImage =name); |
| 331 | +} |
| 332 | + } |
| 333 | +rs.close(); |
| 334 | + }catch(SQLExceptionex) { |
| 335 | +label.setText(ex.toString()); |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | +publicvoiditemStateChanged(ItemEvente) { |
| 340 | +displayImage(list.getItem(((Integer)e.getItem()).intValue())); |
| 341 | + } |
| 342 | + |
| 343 | +/** |
| 344 | + * This is the command line instructions |
| 345 | + */ |
| 346 | +publicstaticvoidinstructions() |
| 347 | + { |
| 348 | +System.err.println("java example.ImageViewer jdbc-url user password"); |
| 349 | +System.err.println("\nExamples:\n"); |
| 350 | +System.err.println("java -Djdbc.driver=postgresql.Driver example.ImageViewer jdbc:postgresql:test postgres password\n"); |
| 351 | + |
| 352 | +System.err.println("This example tests the binary large object api of the driver.\nBasically, it will allow you to store and view images held in the database."); |
| 353 | +System.err.println("Note: If you are running this for the first time on a particular database,\nyou have to select\"Initialise\" in the\"PostgreSQL\" menu.\nThis will create a table used to store image names."); |
| 354 | + } |
| 355 | + |
| 356 | +/** |
| 357 | + * This is the application entry point |
| 358 | + */ |
| 359 | +publicstaticvoidmain(Stringargs[]) |
| 360 | + { |
| 361 | +if(args.length!=3) { |
| 362 | +instructions(); |
| 363 | +System.exit(1); |
| 364 | + } |
| 365 | + |
| 366 | +try { |
| 367 | +Frameframe =newFrame("PostgreSQL ImageViewer v6.3 rev 1"); |
| 368 | +frame.setLayout(newBorderLayout()); |
| 369 | +ImageViewerviewer =newImageViewer(frame,args[0],args[1],args[2]); |
| 370 | +frame.pack(); |
| 371 | +frame.setVisible(true); |
| 372 | + }catch(Exceptionex) { |
| 373 | +System.err.println("Exception caught.\n"+ex); |
| 374 | +ex.printStackTrace(); |
| 375 | + } |
| 376 | + } |
| 377 | +} |