1 20 21 package org.apache.directory.ldapstudio.ldifeditor.editor; 22 23 24 import java.io.BufferedReader ; 25 import java.io.BufferedWriter ; 26 import java.io.File ; 27 import java.io.FileNotFoundException ; 28 import java.io.FileReader ; 29 import java.io.FileWriter ; 30 import java.io.IOException ; 31 import java.io.Reader ; 32 import java.io.Writer ; 33 import java.util.ArrayList ; 34 import java.util.List ; 35 36 import org.apache.directory.ldapstudio.browser.core.BrowserCoreConstants; 37 import org.apache.directory.ldapstudio.browser.core.model.ldif.LdifFile; 38 import org.apache.directory.ldapstudio.browser.core.model.ldif.container.LdifContainer; 39 import org.apache.directory.ldapstudio.browser.core.model.ldif.container.LdifRecord; 40 import org.apache.directory.ldapstudio.browser.core.model.ldif.parser.LdifParser; 41 import org.apache.directory.ldapstudio.ldifeditor.LdifEditorActivator; 42 import org.apache.directory.ldapstudio.ldifeditor.editor.text.LdifExternalAnnotationModel; 43 import org.eclipse.core.runtime.CoreException; 44 import org.eclipse.core.runtime.IPath; 45 import org.eclipse.core.runtime.IProgressMonitor; 46 import org.eclipse.core.runtime.IStatus; 47 import org.eclipse.core.runtime.Status; 48 import org.eclipse.jface.operation.IRunnableContext; 49 import org.eclipse.jface.text.Document; 50 import org.eclipse.jface.text.DocumentEvent; 51 import org.eclipse.jface.text.IDocument; 52 import org.eclipse.jface.text.IDocumentListener; 53 import org.eclipse.jface.text.Region; 54 import org.eclipse.jface.text.TextUtilities; 55 import org.eclipse.jface.text.source.IAnnotationModel; 56 import org.eclipse.ui.IEditorInput; 57 import org.eclipse.ui.IPathEditorInput; 58 import org.eclipse.ui.texteditor.AbstractDocumentProvider; 59 60 61 68 public class LdifDocumentProvider extends AbstractDocumentProvider implements IDocumentListener 69 { 70 71 private final LdifParser ldifParser; 72 73 private final LdifDocumentSetupParticipant ldifDocumentSetupParticipant; 74 75 private LdifFile ldifModel; 76 77 78 81 public LdifDocumentProvider() 82 { 83 super(); 84 this.ldifParser = new LdifParser(); 85 this.ldifDocumentSetupParticipant = new LdifDocumentSetupParticipant(); 86 } 87 88 89 92 public IDocument getDocument( Object element ) 93 { 94 IDocument document = super.getDocument( element ); 95 return document; 96 } 97 98 99 105 public LdifFile getLdifModel() 106 { 107 return ldifModel; 108 } 109 110 111 114 public void documentAboutToBeChanged( DocumentEvent event ) 115 { 116 } 117 118 119 122 public void documentChanged( DocumentEvent event ) 123 { 124 try 125 { 126 int changeOffset = event.getOffset(); 127 int replacedTextLength = event.getLength(); 128 int insertedTextLength = event.getText() != null ? event.getText().length() : 0; 129 IDocument document = event.getDocument(); 130 Region changeRegion = new Region( changeOffset - BrowserCoreConstants.LINE_SEPARATOR.length(), 133 replacedTextLength + ( 2 * BrowserCoreConstants.LINE_SEPARATOR.length() ) ); 134 135 List <LdifContainer> oldContainerList = new ArrayList <LdifContainer>(); 138 LdifContainer[] containers = this.ldifModel.getContainers(); 139 for ( int i = 0; i < containers.length; i++ ) 140 { 141 142 Region containerRegion = new Region( containers[i].getOffset(), containers[i].getLength() ); 143 144 boolean changeOffsetAtEOF = i == containers.length - 1 145 && changeOffset >= containerRegion.getOffset() + containerRegion.getLength(); 146 147 if ( TextUtilities.overlaps( containerRegion, changeRegion ) || changeOffsetAtEOF ) 148 { 149 150 int index = i; 152 153 i--; 155 for ( ; i >= 0; i-- ) 156 { 157 if ( !containers[i].isValid() || !( containers[i] instanceof LdifRecord ) ) 158 { 159 oldContainerList.add( 0, containers[i] ); 160 } 161 else 162 { 163 break; 164 } 165 } 166 167 i = index; 169 for ( ; i < containers.length; i++ ) 170 { 171 containerRegion = new Region( containers[i].getOffset(), containers[i].getLength() ); 172 if ( TextUtilities.overlaps( containerRegion, changeRegion ) || changeOffsetAtEOF ) 173 { 174 oldContainerList.add( containers[i] ); 175 } 176 else 177 { 178 break; 179 } 180 } 181 182 for ( ; i < containers.length; i++ ) 184 { 185 if ( !containers[i].isValid() || !( containers[i] instanceof LdifRecord ) 186 || !( oldContainerList.get( oldContainerList.size() - 1 ) instanceof LdifRecord ) ) 187 { 188 oldContainerList.add( containers[i] ); 189 } 190 else 191 { 192 break; 193 } 194 } 195 } 196 } 197 LdifContainer[] oldContainers = ( LdifContainer[] ) oldContainerList 198 .toArray( new LdifContainer[oldContainerList.size()] ); 199 int oldCount = oldContainers.length; 200 int oldOffset = oldCount > 0 ? oldContainers[0].getOffset() : 0; 201 int oldLength = oldCount > 0 ? ( oldContainers[oldContainers.length - 1].getOffset() 202 + oldContainers[oldContainers.length - 1].getLength() - oldContainers[0].getOffset() ) : 0; 203 204 int newOffset = oldOffset; 206 int newLength = oldLength - replacedTextLength + insertedTextLength; 207 String textToParse = document.get( newOffset, newLength ); 208 209 LdifFile newModel = this.ldifParser.parse( textToParse ); 211 LdifContainer[] newContainers = newModel.getContainers(); 212 213 this.ldifModel.replace( oldContainers, newContainers ); 216 217 } 218 catch ( Exception e ) 219 { 220 e.printStackTrace(); 221 } 222 223 } 224 225 226 229 protected IAnnotationModel createAnnotationModel( Object element ) throws CoreException 230 { 231 return new LdifExternalAnnotationModel(); 232 } 233 234 235 245 private boolean setDocumentContent( IDocument document, IEditorInput input ) throws CoreException 246 { 247 Reader reader; 249 try 250 { 251 if ( input instanceof IPathEditorInput ) 252 { 253 reader = new FileReader ( ( ( IPathEditorInput ) input ).getPath().toFile() ); 254 } 255 else 256 { 257 return false; 258 } 259 } 260 catch ( FileNotFoundException e ) 261 { 262 return true; 264 } 265 266 try 267 { 268 setDocumentContent( document, reader ); 269 return true; 270 } 271 catch ( IOException e ) 272 { 273 throw new CoreException( new Status( IStatus.ERROR, LdifEditorActivator.PLUGIN_ID, IStatus.OK, 274 "error reading file", e ) ); } 276 } 277 278 279 286 private void setDocumentContent( IDocument document, Reader reader ) throws IOException 287 { 288 Reader in = new BufferedReader ( reader ); 289 try 290 { 291 StringBuffer buffer = new StringBuffer ( 512 ); 292 char[] readBuffer = new char[512]; 293 int n = in.read( readBuffer ); 294 while ( n > 0 ) 295 { 296 buffer.append( readBuffer, 0, n ); 297 n = in.read( readBuffer ); 298 } 299 300 document.set( buffer.toString() ); 301 302 } 303 finally 304 { 305 in.close(); 306 } 307 } 308 309 310 315 private void setupDocument( IDocument document ) 316 { 317 318 ldifDocumentSetupParticipant.setup( document ); 320 321 this.ldifModel = this.ldifParser.parse( document.get() ); 323 324 document.addDocumentListener( this ); 326 327 } 328 329 330 333 protected void disposeElementInfo( Object element, ElementInfo info ) 334 { 335 IDocument document = info.fDocument; 336 document.removeDocumentListener( this ); 337 338 super.disposeElementInfo( element, info ); 339 } 340 341 342 345 protected IDocument createDocument( Object element ) throws CoreException 346 { 347 if ( element instanceof IEditorInput ) 348 { 349 IDocument document = new Document(); 350 if ( setDocumentContent( document, ( IEditorInput ) element ) ) 351 { 352 setupDocument( document ); 353 } 354 return document; 355 } 356 357 return null; 358 } 359 360 361 364 protected void doSaveDocument( IProgressMonitor monitor, Object element, IDocument document, boolean overwrite ) 365 throws CoreException 366 { 367 368 if ( element instanceof IPathEditorInput ) 369 { 370 IPathEditorInput pei = ( IPathEditorInput ) element; 371 IPath path = pei.getPath(); 372 File file = path.toFile(); 373 374 try 375 { 376 file.createNewFile(); 377 378 if ( file.exists() ) 379 { 380 if ( file.canWrite() ) 381 { 382 Writer writer = new FileWriter ( file ); 383 writeDocumentContent( document, writer, monitor ); 384 } 385 else 386 { 387 throw new CoreException( new Status( IStatus.ERROR, 388 "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "file is read-only", null ) ); } 390 } 391 else 392 { 393 throw new CoreException( new Status( IStatus.ERROR, 394 "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "error creating file", null ) ); } 396 } 397 catch ( IOException e ) 398 { 399 throw new CoreException( new Status( IStatus.ERROR, 400 "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "error when saving file", e ) ); } 402 403 } 404 } 405 406 407 415 private void writeDocumentContent( IDocument document, Writer writer, IProgressMonitor monitor ) throws IOException 416 { 417 Writer out = new BufferedWriter ( writer ); 418 try 419 { 420 out.write( document.get() ); 421 } 422 finally 423 { 424 out.close(); 425 } 426 } 427 428 429 432 protected IRunnableContext getOperationRunner( IProgressMonitor monitor ) 433 { 434 return null; 435 } 436 437 438 441 public boolean isModifiable( Object element ) 442 { 443 if ( element instanceof IPathEditorInput ) 444 { 445 IPathEditorInput pei = ( IPathEditorInput ) element; 446 File file = pei.getPath().toFile(); 447 return file.canWrite() || !file.exists(); } 449 return false; 450 } 451 452 453 456 public boolean isReadOnly( Object element ) 457 { 458 return !isModifiable( element ); 459 } 460 461 462 465 public boolean isStateValidated( Object element ) 466 { 467 return true; 468 } 469 } | Popular Tags |