1 /* 2 * File : ShareResourceDirContentsImpl.java 3 * Created : 02-Jan-2004 4 * By : parg 5 * 6 * Azureus - a Java Bittorrent client 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details ( see the LICENSE file ). 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 package org.gudy.azureus2.pluginsimpl.local.sharing; 24 25 /** 26 * @author parg 27 * 28 */ 29 30 import java.io.*; 31 import java.util.*; 32 33 import org.gudy.azureus2.plugins.sharing.*; 34 import org.gudy.azureus2.plugins.torrent.TorrentAttribute; 35 import org.gudy.azureus2.core3.util.*; 36 import org.gudy.azureus2.core3.internat.*; 37 38 public class 39 ShareResourceDirContentsImpl 40 extends ShareResourceImpl 41 implements ShareResourceDirContents 42 { 43 private final File root; 44 private final boolean recursive; 45 private final Map<String,String> properties; 46 private final byte[] personal_key; 47 48 protected ShareResource[] children = new ShareResource[0]; 49 50 protected ShareResourceDirContentsImpl( ShareManagerImpl _manager, File _dir, boolean _recursive, boolean _personal, Map<String,String> _properties, boolean _async_check )51 ShareResourceDirContentsImpl( 52 ShareManagerImpl _manager, 53 File _dir, 54 boolean _recursive, 55 boolean _personal, 56 Map<String,String> _properties, 57 boolean _async_check ) 58 59 throws ShareException 60 { 61 super( _manager, ST_DIR_CONTENTS ); 62 63 root = _dir; 64 recursive = _recursive; 65 properties = _properties; 66 67 if ( !root.exists()){ 68 69 throw( new ShareException( "Dir '" + root.getName() + "' not found")); 70 } 71 72 if ( root.isFile()){ 73 74 throw( new ShareException( "Not a directory")); 75 } 76 77 personal_key = _personal?RandomUtils.nextSecureHash():null; 78 79 // new resource, trigger processing 80 81 if ( _async_check ){ 82 83 new AEThread2( "SM:asyncCheck", true ) 84 { 85 public void 86 run() 87 { 88 try{ 89 checkConsistency(); 90 91 }catch( Throwable e ){ 92 93 Debug.out( "Failed to update consistency", e ); 94 } 95 } 96 }.start(); 97 98 }else{ 99 100 checkConsistency(); 101 } 102 } 103 104 protected ShareResourceDirContentsImpl( ShareManagerImpl _manager, File _dir, boolean _recursive, Map _map )105 ShareResourceDirContentsImpl( 106 ShareManagerImpl _manager, 107 File _dir, 108 boolean _recursive, 109 Map _map ) 110 111 throws ShareException 112 { 113 super( _manager, ST_DIR_CONTENTS, _map ); 114 115 root = _dir; 116 recursive = _recursive; 117 118 // recovery - see comment below about not failing if dir doesn't exist... 119 120 if ( !root.exists()){ 121 122 Debug.out( "Dir '" + root.getName() + "' not found"); 123 124 // throw( new ShareException( "Dir '".concat(root.getName()).concat("' not found"))); 125 126 }else{ 127 128 if ( root.isFile()){ 129 130 throw( new ShareException( "Not a directory")); 131 } 132 } 133 134 personal_key = (byte[])_map.get( "per_key" ); 135 136 properties = BDecoder.decodeStrings((Map)_map.get( "props" )); 137 138 // deserialised resource, checkConsistency will be called later to trigger sub-share adding 139 } 140 141 public boolean canBeDeleted()142 canBeDeleted() 143 144 throws ShareResourceDeletionVetoException 145 { 146 for (int i=0;i<children.length;i++){ 147 148 if ( !children[i].canBeDeleted()){ 149 150 return( false ); 151 } 152 } 153 154 return( true ); 155 } 156 157 protected void checkConsistency()158 checkConsistency() 159 160 throws ShareException 161 { 162 // ensure all shares are defined as per dir contents and recursion flag 163 164 List kids = checkConsistency(root); 165 166 if ( kids != null ){ 167 168 children = new ShareResource[kids.size()]; 169 170 kids.toArray( children ); 171 172 }else{ 173 174 children = new ShareResource[0]; 175 } 176 } 177 178 protected List checkConsistency( File dir )179 checkConsistency( 180 File dir ) 181 182 throws ShareException 183 { 184 List kids = new ArrayList(); 185 186 File[] files = dir.listFiles(); 187 188 if ( files == null || !dir.exists() ){ 189 190 // dir has been deleted 191 192 if ( !isPersistent()){ 193 194 // actually, this can be bad as some os errors (e.g. "too many open files") can cause the dir 195 // to appear to have been deleted. However, we don't want to delete the share. So let's just 196 // leave it around, manual delete required if deletion required. 197 198 if ( dir == root ){ 199 200 return( null ); 201 202 }else{ 203 204 manager.delete( this, true ); 205 } 206 } 207 }else{ 208 209 for (int i=0;i<files.length;i++){ 210 211 File file = files[i]; 212 213 String file_name = file.getName(); 214 215 if (!(file_name.equals(".") || file_name.equals(".." ))){ 216 217 if ( file.isDirectory()){ 218 219 if ( recursive ){ 220 221 List child = checkConsistency( file ); 222 223 kids.add( new shareNode( this, file, child )); 224 225 }else{ 226 227 try{ 228 ShareResource res = manager.getDir( file ); 229 230 if ( res == null ){ 231 232 res = manager.addDir( this, file, personal_key != null, properties ); 233 } 234 235 kids.add( res ); 236 237 }catch( Throwable e ){ 238 239 Debug.printStackTrace( e ); 240 } 241 } 242 }else{ 243 244 try{ 245 ShareResource res = manager.getFile( file ); 246 247 if ( res == null ){ 248 249 res = manager.addFile( this, file, personal_key != null, properties ); 250 } 251 252 kids.add( res ); 253 254 }catch( Throwable e ){ 255 256 Debug.printStackTrace( e ); 257 } 258 } 259 } 260 } 261 262 for (int i=0;i<kids.size();i++){ 263 264 Object o = kids.get(i); 265 266 if ( o instanceof ShareResourceImpl ){ 267 268 ((ShareResourceImpl)o).setParent(this); 269 }else{ 270 271 ((shareNode)o).setParent(this); 272 } 273 } 274 } 275 276 return( kids ); 277 } 278 279 protected void deleteInternal()280 deleteInternal() 281 { 282 for (int i=0;i<children.length;i++){ 283 284 try{ 285 if ( children[i] instanceof ShareResourceImpl ){ 286 287 ((ShareResourceImpl)children[i]).delete(true); 288 }else{ 289 290 ((shareNode)children[i]).delete(true); 291 292 } 293 }catch( Throwable e ){ 294 295 Debug.printStackTrace( e ); 296 } 297 } 298 } 299 300 protected void serialiseResource( Map map )301 serialiseResource( 302 Map map ) 303 { 304 super.serialiseResource( map ); 305 306 map.put( "type", new Long(getType())); 307 308 map.put( "recursive", new Long(recursive?1:0)); 309 310 try{ 311 map.put( "file", root.toString().getBytes( Constants.DEFAULT_ENCODING)); 312 313 }catch( UnsupportedEncodingException e ){ 314 315 Debug.printStackTrace( e ); 316 } 317 318 if ( personal_key != null ){ 319 320 map.put( "per_key", personal_key ); 321 } 322 323 if ( properties != null ){ 324 325 map.put( "props", properties ); 326 } 327 } 328 329 protected static ShareResourceImpl deserialiseResource( ShareManagerImpl manager, Map map )330 deserialiseResource( 331 ShareManagerImpl manager, 332 Map map ) 333 334 throws ShareException 335 { 336 try{ 337 File root = new File(new String((byte[])map.get("file"), Constants.DEFAULT_ENCODING)); 338 339 boolean recursive = ((Long)map.get("recursive")).longValue() == 1; 340 341 ShareResourceImpl res = new ShareResourceDirContentsImpl( manager, root, recursive, map ); 342 343 return( res ); 344 345 }catch( UnsupportedEncodingException e ){ 346 347 throw( new ShareException( "internal error", e )); 348 } 349 } 350 351 public String getName()352 getName() 353 { 354 return( root.toString()); 355 } 356 357 public File getRoot()358 getRoot() 359 { 360 return( root ); 361 } 362 363 public boolean isRecursive()364 isRecursive() 365 { 366 return( recursive ); 367 } 368 369 public ShareResource[] getChildren()370 getChildren() 371 { 372 return( children ); 373 } 374 375 public Map<String, String> getProperties()376 getProperties() 377 { 378 return( properties ); 379 } 380 381 protected class 382 shareNode 383 implements ShareResourceDirContents 384 { 385 protected ShareResourceDirContents node_parent; 386 protected File node; 387 protected ShareResource[] node_children; 388 389 protected shareNode( ShareResourceDirContents _parent, File _node, List kids )390 shareNode( 391 ShareResourceDirContents _parent, 392 File _node, 393 List kids ) 394 { 395 node_parent = _parent; 396 node =_node; 397 398 node_children = new ShareResource[kids.size()]; 399 400 kids.toArray( node_children ); 401 402 for (int i=0;i<node_children.length;i++){ 403 404 Object o = node_children[i]; 405 406 if ( o instanceof ShareResourceImpl ){ 407 408 ((ShareResourceImpl)o).setParent( this ); 409 }else{ 410 411 ((shareNode)o).setParent( this ); 412 413 } 414 } 415 } 416 417 public ShareResourceDirContents getParent()418 getParent() 419 { 420 return( node_parent ); 421 } 422 423 protected void setParent( ShareResourceDirContents _parent )424 setParent( 425 ShareResourceDirContents _parent ) 426 { 427 node_parent = _parent; 428 } 429 430 public int getType()431 getType() 432 { 433 return( ShareResource.ST_DIR_CONTENTS ); 434 } 435 436 public String getName()437 getName() 438 { 439 return( node.toString()); 440 } 441 442 public void setAttribute( TorrentAttribute attribute, String value )443 setAttribute( 444 TorrentAttribute attribute, 445 String value ) 446 { 447 for (int i=0;i<node_children.length;i++){ 448 449 node_children[i].setAttribute( attribute, value ); 450 } 451 } 452 453 public String getAttribute( TorrentAttribute attribute )454 getAttribute( 455 TorrentAttribute attribute ) 456 { 457 return( null ); 458 } 459 460 public TorrentAttribute[] getAttributes()461 getAttributes() 462 { 463 return( new TorrentAttribute[0]); 464 } 465 466 public void delete()467 delete() 468 469 throws ShareResourceDeletionVetoException 470 { 471 throw( new ShareResourceDeletionVetoException( MessageText.getString("plugin.sharing.remove.veto"))); 472 } 473 474 public void delete( boolean force )475 delete( 476 boolean force ) 477 478 throws ShareException, ShareResourceDeletionVetoException 479 { 480 for (int i=0;i<node_children.length;i++){ 481 482 Object o = node_children[i]; 483 484 if ( o instanceof ShareResourceImpl ){ 485 486 ((ShareResourceImpl)o).delete(force); 487 }else{ 488 489 ((shareNode)o).delete(force); 490 } 491 } 492 } 493 494 495 public boolean canBeDeleted()496 canBeDeleted() 497 498 throws ShareResourceDeletionVetoException 499 { 500 for (int i=0;i<node_children.length;i++){ 501 502 node_children[i].canBeDeleted(); 503 } 504 505 return( true ); 506 } 507 508 public File getRoot()509 getRoot() 510 { 511 return( node ); 512 } 513 514 public boolean isRecursive()515 isRecursive() 516 { 517 return( recursive ); 518 } 519 520 public ShareResource[] getChildren()521 getChildren() 522 { 523 return( node_children ); 524 } 525 526 public Map<String, String> getProperties()527 getProperties() 528 { 529 return( null ); 530 } 531 532 public boolean isPersistent()533 isPersistent() 534 { 535 return( false ); 536 } 537 538 public void addChangeListener( ShareResourceListener l )539 addChangeListener( 540 ShareResourceListener l ) 541 { 542 } 543 544 public void removeChangeListener( ShareResourceListener l )545 removeChangeListener( 546 ShareResourceListener l ) 547 { 548 } 549 550 public void addDeletionListener( ShareResourceWillBeDeletedListener l )551 addDeletionListener( 552 ShareResourceWillBeDeletedListener l ) 553 { 554 } 555 556 public void removeDeletionListener( ShareResourceWillBeDeletedListener l )557 removeDeletionListener( 558 ShareResourceWillBeDeletedListener l ) 559 { 560 } 561 } 562 } 563