1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package org.eclipse.jdt.internal.ui.propertiesfileeditor;
14 import java.io.ByteArrayInputStream;
15 import java.io.IOException;
16 import java.text.StringCharacterIterator;
17 import java.util.Properties;
19 import org.eclipse.swt.widgets.Display;
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.BadPartitioningException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IDocumentExtension3;
25 import org.eclipse.jface.text.IRegion;
26 import org.eclipse.jface.text.ITextViewer;
27 import org.eclipse.jface.text.ITypedRegion;
28 import org.eclipse.jface.text.Region;
29 import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
30 import org.eclipse.jface.text.hyperlink.IHyperlink;
32 import org.eclipse.ui.IEditorSite;
33 import org.eclipse.ui.IFileEditorInput;
34 import org.eclipse.ui.IStorageEditorInput;
36 import org.eclipse.ui.texteditor.IEditorStatusLine;
37 import org.eclipse.ui.texteditor.ITextEditor;
41 * Properties key hyperlink detector.
43 * XXX: This does not work for properties files coming from a JAR due to missing J Core
44 * functionality. For details see http://bugs.eclipse.org/22376
49 public class PropertyKeyHyperlinkDetector extends AbstractHyperlinkDetector {
52 * @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion, boolean)
54 public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
55 ITextEditor textEditor= (ITextEditor)getAdapter(ITextEditor.class);
56 if (region == null || textEditor == null)
59 IEditorSite site= textEditor.getEditorSite();
63 int offset= region.getOffset();
64 if (!checkEnabled(textEditor, offset))
67 ITypedRegion partition= null;
69 IStorageEditorInput storageEditorInput= (IStorageEditorInput)textEditor.getEditorInput();
70 IDocument document= textEditor.getDocumentProvider().getDocument(storageEditorInput);
71 if (document instanceof IDocumentExtension3)
72 partition= ((IDocumentExtension3)document).getPartition(IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING, offset, false);
74 // Check whether it is the correct partition
75 if (partition == null || !IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
79 // Check whether the partition covers the selection
80 if (offset + region.getLength() > partition.getOffset() + partition.getLength()) {
84 // Extract the key from the partition (which contains key and assignment
85 String key= document.get(partition.getOffset(), partition.getLength());
87 String realKey= key.trim();
88 int delta= key.indexOf(realKey);
90 String unicodeKey= getUnicodeString(realKey);
91 // Check whether the key is valid
92 Properties properties= new Properties();
93 properties.load(new ByteArrayInputStream(document.get().getBytes()));
94 if (properties.getProperty(unicodeKey) == null) {
98 return new PropertyKeyHyperlink[] { new PropertyKeyHyperlink(new Region(partition.getOffset() + delta, realKey.length()), realKey, textEditor) };
100 } catch (BadLocationException ex) {
102 } catch (BadPartitioningException ex) {
104 } catch (IOException ex) {
106 } catch (IllegalArgumentException ex) {
107 showErrorInStatusLine(ex.getLocalizedMessage(), textEditor);
112 private String getUnicodeString(String key) {
113 StringCharacterIterator iter= new StringCharacterIterator(key);
114 StringBuffer result= new StringBuffer();
115 while (iter.getIndex() < iter.getEndIndex()) {
116 char c= iter.current();
121 StringBuffer unicode= new StringBuffer();
122 unicode.append(iter.next());
123 unicode.append(iter.next());
124 unicode.append(iter.next());
125 unicode.append(iter.next());
126 c= (char)Integer.parseInt(unicode.toString(), 16);
132 return result.toString();
135 private boolean checkEnabled(ITextEditor textEditor, int offset) {
139 // XXX: Must be changed to IStorageEditorInput once support for JARs is available (see class Javadoc for details)
140 return textEditor.getEditorInput() instanceof IFileEditorInput;
143 private void showErrorInStatusLine(final String message, ITextEditor textEditor) {
144 Display display= textEditor.getEditorSite().getShell().getDisplay();
146 final IEditorStatusLine statusLine= (IEditorStatusLine)textEditor.getAdapter(IEditorStatusLine.class);
147 if (statusLine != null) {
148 display.asyncExec(new Runnable() {
150 * @see java.lang.Runnable#run()
153 statusLine.setMessage(true, message, null);