1 11 package org.eclipse.jdt.internal.ui.propertiesfileeditor; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import com.ibm.icu.text.Collator; 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.List ; 18 import java.util.regex.Pattern ; 19 20 import org.eclipse.core.runtime.Assert; 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IAdaptable; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 import org.eclipse.core.runtime.IStatus; 25 import org.eclipse.core.runtime.NullProgressMonitor; 26 import org.eclipse.core.runtime.PlatformObject; 27 import org.eclipse.core.runtime.Status; 28 import org.eclipse.core.runtime.SubProgressMonitor; 29 30 import org.eclipse.core.filebuffers.FileBuffers; 31 import org.eclipse.core.filebuffers.ITextFileBuffer; 32 import org.eclipse.core.filebuffers.ITextFileBufferManager; 33 import org.eclipse.core.filebuffers.LocationKind; 34 35 import org.eclipse.core.resources.IResource; 36 import org.eclipse.core.resources.IStorage; 37 38 import org.eclipse.swt.widgets.Shell; 39 40 import org.eclipse.jface.dialogs.ErrorDialog; 41 import org.eclipse.jface.dialogs.MessageDialog; 42 import org.eclipse.jface.operation.IRunnableWithProgress; 43 import org.eclipse.jface.resource.ImageDescriptor; 44 import org.eclipse.jface.viewers.ILabelProvider; 45 import org.eclipse.jface.window.Window; 46 47 import org.eclipse.jface.text.BadLocationException; 48 import org.eclipse.jface.text.IDocument; 49 import org.eclipse.jface.text.IRegion; 50 import org.eclipse.jface.text.hyperlink.IHyperlink; 51 52 import org.eclipse.ui.IEditorPart; 53 import org.eclipse.ui.IStorageEditorInput; 54 import org.eclipse.ui.PartInitException; 55 import org.eclipse.ui.dialogs.TwoPaneElementSelector; 56 import org.eclipse.ui.model.IWorkbenchAdapter; 57 import org.eclipse.ui.model.WorkbenchLabelProvider; 58 import org.eclipse.ui.texteditor.IEditorStatusLine; 59 import org.eclipse.ui.texteditor.ITextEditor; 60 61 import org.eclipse.search.core.text.TextSearchEngine; 62 import org.eclipse.search.core.text.TextSearchMatchAccess; 63 import org.eclipse.search.core.text.TextSearchRequestor; 64 import org.eclipse.search.core.text.TextSearchScope; 65 66 import org.eclipse.jdt.core.IJavaElement; 67 import org.eclipse.jdt.core.JavaCore; 68 import org.eclipse.jdt.core.JavaModelException; 69 import org.eclipse.jdt.core.search.IJavaSearchConstants; 70 import org.eclipse.jdt.core.search.IJavaSearchScope; 71 import org.eclipse.jdt.core.search.SearchEngine; 72 import org.eclipse.jdt.core.search.SearchMatch; 73 import org.eclipse.jdt.core.search.SearchPattern; 74 import org.eclipse.jdt.core.search.SearchRequestor; 75 76 import org.eclipse.jdt.internal.corext.util.Messages; 77 import org.eclipse.jdt.internal.corext.util.SearchUtils; 78 79 import org.eclipse.jdt.ui.JavaUI; 80 81 import org.eclipse.jdt.internal.ui.IJavaStatusConstants; 82 import org.eclipse.jdt.internal.ui.JavaPlugin; 83 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; 84 import org.eclipse.jdt.internal.ui.util.ExceptionHandler; 85 import org.eclipse.jdt.internal.ui.util.PatternConstructor; 86 87 88 98 public class PropertyKeyHyperlink implements IHyperlink { 99 100 101 private static class KeyReference extends PlatformObject implements IWorkbenchAdapter, Comparable { 102 103 private static final Collator fgCollator= Collator.getInstance(); 104 105 private IStorage storage; 106 private int offset; 107 private int length; 108 109 110 private KeyReference(IStorage storage, int offset, int length) { 111 Assert.isNotNull(storage); 112 this.storage= storage; 113 this.offset= offset; 114 this.length= length; 115 } 116 117 120 public Object getAdapter(Class adapter) { 121 if (adapter == IWorkbenchAdapter.class) 122 return this; 123 else 124 return super.getAdapter(adapter); 125 } 126 129 public Object [] getChildren(Object o) { 130 return null; 131 } 132 135 public ImageDescriptor getImageDescriptor(Object object) { 136 IWorkbenchAdapter wbAdapter= (IWorkbenchAdapter)storage.getAdapter(IWorkbenchAdapter.class); 137 if (wbAdapter != null) 138 return wbAdapter.getImageDescriptor(storage); 139 return null; 140 } 141 144 public String getLabel(Object o) { 145 146 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); 147 try { 148 manager.connect(storage.getFullPath(), LocationKind.NORMALIZE, null); 149 try { 150 ITextFileBuffer buffer= manager.getTextFileBuffer(storage.getFullPath(), LocationKind.NORMALIZE); 151 IDocument document= buffer.getDocument(); 152 if (document != null) { 153 int line= document.getLineOfOffset(offset) + 1; 154 Object [] args= new Object [] { new Integer (line), storage.getFullPath() }; 155 return Messages.format(PropertiesFileEditorMessages.OpenAction_SelectionDialog_elementLabel, args); 156 } 157 } finally { 158 manager.disconnect(storage.getFullPath(), LocationKind.NORMALIZE, null); 159 } 160 } catch (CoreException e) { 161 JavaPlugin.log(e.getStatus()); 162 } catch (BadLocationException e) { 163 JavaPlugin.log(e); 164 } 165 166 return storage.getFullPath().toString(); 167 } 168 171 public Object getParent(Object o) { 172 return null; 173 } 174 175 public int compareTo(Object o) { 176 KeyReference otherRef= (KeyReference)o; 177 String thisPath= storage.getFullPath().toString(); 178 String otherPath= otherRef.storage.getFullPath().toString(); 179 int result= fgCollator.compare(thisPath, otherPath); 180 if (result != 0) 181 return result; 182 else 183 return offset - otherRef.offset; 184 } 185 } 186 187 188 private static class ResultCollector extends TextSearchRequestor { 189 190 private List fResult; 191 private boolean fIsKeyDoubleQuoted; 192 193 public ResultCollector(List result, boolean isKeyDoubleQuoted) { 194 fResult= result; 195 fIsKeyDoubleQuoted= isKeyDoubleQuoted; 196 } 197 198 public boolean acceptPatternMatch(TextSearchMatchAccess matchAccess) throws CoreException { 199 int start= matchAccess.getMatchOffset(); 200 int length= matchAccess.getMatchLength(); 201 202 if (fIsKeyDoubleQuoted) { 203 start= start + 1; 204 length= length - 2; 205 } 206 fResult.add(new KeyReference(matchAccess.getFile(), start, length)); 207 return true; 208 } 209 } 210 211 212 private IRegion fRegion; 213 private String fPropertiesKey; 214 private Shell fShell; 215 private IStorage fStorage; 216 private ITextEditor fEditor; 217 218 219 226 public PropertyKeyHyperlink(IRegion region, String key, ITextEditor editor) { 227 Assert.isNotNull(region); 228 Assert.isNotNull(key); 229 Assert.isNotNull(editor); 230 231 fRegion= region; 232 fPropertiesKey= key; 233 fEditor= editor; 234 IStorageEditorInput storageEditorInput= (IStorageEditorInput)fEditor.getEditorInput(); 235 fShell= fEditor.getEditorSite().getShell(); 236 try { 237 fStorage= storageEditorInput.getStorage(); 238 } catch (CoreException e) { 239 fStorage= null; 240 } 241 } 242 243 246 public IRegion getHyperlinkRegion() { 247 return fRegion; 248 } 249 250 253 public void open() { 254 if (!checkEnabled()) 255 return; 256 257 IResource resource= (IResource)fStorage; 259 KeyReference[] references= null; 260 if (resource != null) 261 references= search(resource.getProject(), fPropertiesKey); 262 263 if (references == null) 264 return; 266 if (references.length == 0) { 267 String message= PropertiesFileEditorMessages.OpenAction_error_messageNoResult; 268 showErrorInStatusLine(message); 269 return; 270 } 271 272 open(references); 273 274 } 275 276 private boolean checkEnabled() { 277 return fStorage instanceof IResource; 279 } 280 281 private void open(KeyReference[] keyReferences) { 282 Assert.isLegal(keyReferences != null && keyReferences.length > 0); 283 284 if (keyReferences.length == 1) 285 open(keyReferences[0]); 286 else 287 open(select(keyReferences)); 288 } 289 290 299 private KeyReference select(final KeyReference[] keyReferences) { 300 Arrays.sort(keyReferences); 301 final int length= keyReferences.length; 302 ILabelProvider labelProvider= new WorkbenchLabelProvider() { 303 public String decorateText(String input, Object element) { 304 KeyReference keyRef= (KeyReference)element; 305 IStorage storage= keyRef.storage; 306 String name= storage.getName(); 307 if (name == null) 308 return input; 309 310 int count= 0; 311 for (int i= 0; i < length; i++) { 312 if (keyReferences[i].storage.equals(storage)) 313 count++; 314 } 315 if (count > 1) { 316 Object [] args= new Object [] { name, new Integer (count) }; 317 name= Messages.format(PropertiesFileEditorMessages.OpenAction_SelectionDialog_elementLabelWithMatchCount, args); 318 } 319 320 return name; 321 } 322 }; 323 324 TwoPaneElementSelector dialog= new TwoPaneElementSelector(fShell, labelProvider, new WorkbenchLabelProvider()); 325 dialog.setLowerListLabel(PropertiesFileEditorMessages.OpenAction_SelectionDialog_details); 326 dialog.setMultipleSelection(false); 327 dialog.setTitle(PropertiesFileEditorMessages.OpenAction_SelectionDialog_title); 328 dialog.setMessage(PropertiesFileEditorMessages.OpenAction_SelectionDialog_message); 329 dialog.setElements(keyReferences); 330 331 if (dialog.open() == Window.OK) { 332 Object [] result= dialog.getResult(); 333 if (result != null && result.length == 1) 334 return (KeyReference)result[0]; 335 } 336 337 return null; 338 } 339 340 private void open(KeyReference keyReference) { 341 if (keyReference == null) 342 return; 343 344 try { 345 IEditorPart part= EditorUtility.openInEditor(keyReference.storage, true); 346 EditorUtility.revealInEditor(part, keyReference.offset, keyReference.length); 347 } catch (JavaModelException e) { 348 JavaPlugin.log(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), 349 IJavaStatusConstants.INTERNAL_ERROR, PropertiesFileEditorMessages.OpenAction_error_message, e)); 350 351 ErrorDialog.openError(fShell, 352 getErrorDialogTitle(), 353 PropertiesFileEditorMessages.OpenAction_error_messageProblems, 354 e.getStatus()); 355 356 } catch (PartInitException x) { 357 358 String message= null; 359 360 IWorkbenchAdapter wbAdapter= (IWorkbenchAdapter)((IAdaptable)keyReference).getAdapter(IWorkbenchAdapter.class); 361 if (wbAdapter != null) 362 message= Messages.format(PropertiesFileEditorMessages.OpenAction_error_messageArgs, 363 new String [] { wbAdapter.getLabel(keyReference), x.getLocalizedMessage() } ); 364 365 if (message == null) 366 message= Messages.format(PropertiesFileEditorMessages.OpenAction_error_message, x.getLocalizedMessage()); 367 368 MessageDialog.openError(fShell, 369 PropertiesFileEditorMessages.OpenAction_error_messageProblems, 370 message); 371 } 372 } 373 374 private String getErrorDialogTitle() { 375 return PropertiesFileEditorMessages.OpenAction_error_title; 376 } 377 378 private void showError(CoreException e) { 379 ExceptionHandler.handle(e, fShell, getErrorDialogTitle(), PropertiesFileEditorMessages.OpenAction_error_message); 380 } 381 382 private void showErrorInStatusLine(final String message) { 383 fShell.getDisplay().beep(); 384 final IEditorStatusLine statusLine= (IEditorStatusLine)fEditor.getAdapter(IEditorStatusLine.class); 385 if (statusLine != null) { 386 fShell.getDisplay().asyncExec(new Runnable () { 387 390 public void run() { 391 statusLine.setMessage(true, message, null); 392 } 393 }); 394 } 395 } 396 397 405 private boolean useDoubleQuotedKey() { 406 if (fStorage == null) 407 return false; 408 409 String name= fStorage.getName(); 410 411 return name != null && !"about.properties".equals(name) && !"feature.properties".equals(name) && !"plugin.properties".equals(name); } 413 414 421 private KeyReference[] search(final IResource scope, String key) { 422 if (key == null) 423 return new KeyReference[0]; 424 425 final List result= new ArrayList (5); 426 final String searchString; 427 428 final boolean useDoubleQuotedKey= useDoubleQuotedKey(); 430 if (useDoubleQuotedKey) { 431 StringBuffer buf= new StringBuffer ("\""); buf.append(fPropertiesKey); 433 buf.append('"'); 434 searchString= buf.toString(); 435 } else 436 searchString= fPropertiesKey; 437 438 try { 439 fEditor.getEditorSite().getWorkbenchWindow().getWorkbench().getProgressService().busyCursorWhile( 440 new IRunnableWithProgress() { 441 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 442 if (monitor == null) 443 monitor= new NullProgressMonitor(); 444 445 monitor.beginTask("", 5); try { 447 ResultCollector collector= new ResultCollector(result, useDoubleQuotedKey); 448 TextSearchEngine engine= TextSearchEngine.create(); 449 Pattern searchPattern= PatternConstructor.createPattern(searchString, true, false); 450 engine.search(createScope(scope), collector, searchPattern, new SubProgressMonitor(monitor, 4)); 451 452 if (result.size() == 0 && useDoubleQuotedKey) { 453 IJavaElement element= JavaCore.create(scope); 455 if (element == null) 456 return; 457 458 int includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.REFERENCED_PROJECTS; 459 IJavaSearchScope javaSearchScope= SearchEngine.createJavaSearchScope(new IJavaElement[] { element }, includeMask); 460 461 SearchPattern pattern= SearchPattern.createPattern(fPropertiesKey, IJavaSearchConstants.FIELD, IJavaSearchConstants.REFERENCES, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE); 462 try { 463 new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), javaSearchScope, new SearchRequestor() { 464 public void acceptSearchMatch(SearchMatch match) throws CoreException { 465 result.add(new KeyReference((IStorage)match.getResource(), match.getOffset(), match.getLength())); 466 } 467 }, new SubProgressMonitor(monitor, 1)); 468 } catch (CoreException e) { 469 throw new InvocationTargetException (e); 470 } 471 } else { 472 monitor.worked(1); 473 } 474 } finally { 475 monitor.done(); 476 } 477 } 478 } 479 ); 480 } catch (InvocationTargetException ex) { 481 String message= PropertiesFileEditorMessages.OpenAction_error_messageErrorSearchingKey; 482 showError(new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.OK, message, ex.getTargetException()))); 483 } catch (InterruptedException ex) { 484 return null; } 486 487 return (KeyReference[])result.toArray(new KeyReference[result.size()]); 488 } 489 490 private static TextSearchScope createScope(IResource scope) { 491 ArrayList fileNamePatternStrings= new ArrayList (); 492 493 String [] javaExtensions= JavaCore.getJavaLikeExtensions(); 495 for (int i= 0; i < javaExtensions.length; i++) 496 fileNamePatternStrings.add("*." + javaExtensions[i]); fileNamePatternStrings.add("*.xml"); fileNamePatternStrings.add("*.ini"); 500 String [] allPatternStrings= (String []) fileNamePatternStrings.toArray(new String [fileNamePatternStrings.size()]); 501 Pattern fileNamePattern= PatternConstructor.createPattern(allPatternStrings, false, false); 502 503 return TextSearchScope.newSearchScope(new IResource[] { scope }, fileNamePattern, false); 504 } 505 506 509 public String getTypeLabel() { 510 return null; 511 } 512 513 516 public String getHyperlinkText() { 517 return null; 518 } 519 } 520 | Popular Tags |