1 /* 2 * Created on 27-Apr-2004 3 * Created by Paul Gardner 4 * Copyright (C) Azureus Software, Inc, All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 */ 19 20 package org.gudy.azureus2.pluginsimpl.local.ui.components; 21 22 /** 23 * @author parg 24 * 25 */ 26 27 import java.io.File; 28 import java.io.FileOutputStream; 29 import java.io.OutputStreamWriter; 30 import java.io.PrintWriter; 31 import java.util.Iterator; 32 import java.util.LinkedList; 33 34 import org.gudy.azureus2.core3.util.*; 35 import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeListener; 36 import org.gudy.azureus2.plugins.ui.components.UITextArea; 37 38 39 public class 40 UITextAreaImpl 41 extends UIComponentImpl 42 implements UITextArea 43 { 44 private final boolean enable_history = System.getProperty( "az.logging.keep.ui.history", "true" ).equals( "true" ); 45 46 private int max_size = DEFAULT_MAX_SIZE; 47 private int max_file_size = 20 * max_size; 48 49 PoopWriter pw; 50 int current_file_size; 51 File poop_file; 52 boolean useFile = true; 53 54 AEMonitor file_mon = new AEMonitor("filemon"); 55 56 LinkedList<String> delay_text = new LinkedList<String>(); 57 int delay_size = 0; 58 59 FrequencyLimitedDispatcher dispatcher = 60 new FrequencyLimitedDispatcher( 61 new AERunnable() 62 { 63 public void 64 runSupport() 65 { 66 delayAppend(); 67 } 68 }, 69 500 ); 70 71 public UITextAreaImpl()72 UITextAreaImpl() 73 { 74 setText(""); 75 } 76 77 public void setText( String text )78 setText( 79 String text ) 80 { 81 if ( !enable_history ){ 82 83 return; 84 } 85 86 if ( useFile ){ 87 88 try{ 89 file_mon.enter(); 90 91 if ( pw == null ){ 92 93 pw = new PoopWriter(); 94 95 pw.print(text); 96 97 current_file_size = text.length(); 98 99 return; 100 } 101 }finally{ 102 103 file_mon.exit(); 104 } 105 } 106 107 // has property change listener, or error while doing file (fallthrough) 108 109 if ( text.length() > max_size ){ 110 111 int size_to_show = max_size - 10000; 112 113 if ( size_to_show < 0 ){ 114 115 size_to_show = max_size; 116 } 117 118 text = text.substring( text.length() - size_to_show ); 119 } 120 121 setProperty( PT_VALUE, text ); 122 } 123 124 public void appendText( String text )125 appendText( 126 String text ) 127 { 128 if ( !enable_history ){ 129 130 return; 131 } 132 133 if ( useFile && pw != null ){ 134 135 try{ 136 file_mon.enter(); 137 138 // shrink the file occasionally 139 140 if ( current_file_size > max_file_size ){ 141 142 current_file_size = getFileText().length(); 143 } 144 145 pw.print(text); 146 147 current_file_size += text.length(); 148 149 return; 150 151 }finally{ 152 153 file_mon.exit(); 154 } 155 } 156 157 synchronized( this ){ 158 159 delay_text.addLast( text ); 160 161 delay_size += text.length(); 162 163 while( delay_size > max_size ){ 164 165 if ( delay_text.size() == 0 ){ 166 167 break; 168 } 169 170 String s = (String)delay_text.removeFirst(); 171 172 delay_size -= s.length(); 173 } 174 } 175 176 dispatcher.dispatch(); 177 } 178 179 protected void delayAppend()180 delayAppend() 181 { 182 String str = getText(); 183 184 String text; 185 186 synchronized( this ){ 187 188 if ( delay_text.size() == 1 ){ 189 190 text = (String)delay_text.get(0); 191 192 }else{ 193 194 StringBuffer sb = new StringBuffer( delay_size ); 195 196 Iterator<String> it = delay_text.iterator(); 197 198 while( it.hasNext()){ 199 200 sb.append( it.next()); 201 } 202 203 text = sb.toString(); 204 } 205 206 delay_text.clear(); 207 delay_size = 0; 208 } 209 210 if ( str == null ){ 211 212 setText( text ); 213 214 }else{ 215 216 setText( str + text ); 217 } 218 } 219 220 public String getText()221 getText() 222 { 223 if ( !enable_history ){ 224 225 return( "" ); 226 } 227 228 if ( useFile && pw != null ){ 229 230 return( getFileText()); 231 } 232 233 return((String)getProperty( PT_VALUE )); 234 } 235 236 public void setMaximumSize( int _max_size )237 setMaximumSize( 238 int _max_size ) 239 { 240 max_size = _max_size; 241 } 242 243 private String getFileText()244 getFileText() 245 { 246 try{ 247 file_mon.enter(); 248 249 String text = null; 250 251 if ( pw != null ){ 252 253 pw.close(); 254 255 text = pw.getText(); 256 } 257 258 if ( text == null ){ 259 260 text = ""; 261 } 262 263 pw = null; 264 265 if ( useFile ){ 266 267 pw = new PoopWriter(); 268 269 pw.print(text); 270 271 current_file_size = text.length(); 272 } 273 274 return text; 275 276 }finally{ 277 278 file_mon.exit(); 279 } 280 } 281 282 public void addPropertyChangeListener( UIPropertyChangeListener l )283 addPropertyChangeListener( 284 UIPropertyChangeListener l ) 285 { 286 if ( useFile ){ 287 288 useFile = false; 289 290 setText( getFileText()); 291 } 292 293 super.addPropertyChangeListener(l); 294 } 295 296 protected class 297 PoopWriter 298 { 299 private StringBuffer buffer = new StringBuffer(256); 300 301 private PrintWriter pw; 302 303 private void print( String text )304 print( 305 String text ) 306 { 307 if ( pw == null ){ 308 309 buffer.append( text ); 310 311 if ( buffer.length() > 8*1024 ){ 312 313 if ( poop_file == null ){ 314 315 try{ 316 poop_file = AETemporaryFileHandler.createTempFile(); 317 318 }catch( Throwable e ){ 319 } 320 } 321 322 if ( poop_file != null ){ 323 324 try{ 325 pw = new PrintWriter( new OutputStreamWriter( new FileOutputStream( poop_file ), "UTF-8" )); 326 327 pw.print( buffer.toString()); 328 329 }catch( Throwable e ){ 330 } 331 } 332 333 buffer.setLength( 0 ); 334 } 335 }else{ 336 337 pw.print( text ); 338 } 339 } 340 341 private String getText()342 getText() 343 { 344 if ( poop_file == null ){ 345 346 return( buffer.toString()); 347 348 }else{ 349 350 try{ 351 return( FileUtil.readFileEndAsString( poop_file, max_size, "UTF-8" )); 352 353 }catch( Throwable e ){ 354 355 return( "" ); 356 } 357 } 358 } 359 360 private void close()361 close() 362 { 363 if ( pw != null ){ 364 365 pw.close(); 366 367 pw = null; 368 } 369 } 370 } 371 }