View Javadoc
1 /* ==================================================================== 2 * The Apache Software License, Version 1.1 3 * 4 * Copyright (c) 2000 The Apache Software Foundation. All rights 5 * reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * 3. The end-user documentation included with the redistribution, 20 * if any, must include the following acknowledgment: 21 * "This product includes software developed by the 22 * Apache Software Foundation (http://www.apache.org/)." 23 * Alternately, this acknowledgment may appear in the software itself, 24 * if and wherever such third-party acknowledgments normally appear. 25 * 26 * 4. The names "Apache" and "Apache Software Foundation" must 27 * not be used to endorse or promote products derived from this 28 * software without prior written permission. For written 29 * permission, please contact apache@apache.org. 30 * 31 * 5. Products derived from this software may not be called "Apache", 32 * nor may "Apache" appear in their name, without prior written 33 * permission of the Apache Software Foundation. 34 * 35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This software consists of voluntary contributions made by many 50 * individuals on behalf of the Apache Software Foundation. For more 51 * information on the Apache Software Foundation, please see 52 * <http://www.apache.org/>. 53 * 54 * Portions of this software are based upon public domain software 55 * originally written at the National Center for Supercomputing Applications, 56 * University of Illinois, Urbana-Champaign. 57 */ 58 package com.bonevich.eclipse.logging.popups; 59 60 import com.bonevich.eclipse.logging.LoggingPlugin; 61 import com.bonevich.eclipse.logging.LoggingPluginMessages; 62 import com.bonevich.eclipse.logging.LoggingPluginResources; 63 64 import org.apache.commons.logging.Log; 65 import org.apache.commons.logging.LogFactory; 66 import org.eclipse.core.resources.IProject; 67 import org.eclipse.core.runtime.*; 68 import org.eclipse.jdt.core.*; 69 import org.eclipse.jface.text.*; 70 import org.eclipse.jface.text.IRegion; 71 import org.eclipse.ui.IFileEditorInput; 72 import org.eclipse.ui.actions.WorkspaceModifyOperation; 73 import org.eclipse.ui.texteditor.ITextEditor; 74 75 import java.lang.reflect.InvocationTargetException; 76 import java.util.StringTokenizer; 77 78 /*** 79 * Workhorse for adding logging statements to a given source code editor. 80 * 81 * @author jbonevic 82 */ 83 public class AddLoggingOperation 84 extends WorkspaceModifyOperation 85 implements LoggingPluginResources 86 { 87 private static final Log _logger = LogFactory.getLog(AddLoggingOperation.class); 88 89 private static final String DUPLICATE = "duplicate entry"; 90 private static final String EXISTS = "already exists"; 91 92 private ITextEditor _editor; 93 private ICompilationUnit _unit; 94 private AddLoggingAction _action; 95 private boolean _saveWork = true; 96 97 public AddLoggingOperation( 98 ITextEditor editor, 99 ICompilationUnit cu, 100 AddLoggingAction action, 101 boolean saveWork) 102 { 103 super(); 104 _editor = editor; 105 _unit = cu; 106 _action = action; 107 _saveWork = saveWork; 108 } 109 110 /*** 111 * @see WorkspaceModifyOperation#execute(IProgressMonitor) 112 */ 113 protected void execute(IProgressMonitor monitor) 114 throws CoreException, InvocationTargetException, InterruptedException 115 { 116 if (monitor == null) 117 { 118 monitor = new NullProgressMonitor(); 119 } 120 monitor.beginTask(LoggingPluginMessages.bind(ADD_LOGGING_DIALOG), 3); 121 122 IDocument document = _editor.getDocumentProvider().getDocument(_editor.getEditorInput()); 123 String lineDelimiter = getLineDelimiter(document); 124 int tabWidth = getTabWidth(); 125 String loggingImpl = LoggingPlugin.getPlugin().getLoggingImplementationPreference(); 126 127 linkLoggerLibrary(loggingImpl, monitor); 128 monitor.worked(1); 129 130 addLoggerImports(loggingImpl); 131 monitor.worked(1); 132 133 addLoggerField(loggingImpl, lineDelimiter, tabWidth); 134 monitor.worked(1); 135 136 addLoggingStatement(loggingImpl, document, lineDelimiter, tabWidth); 137 monitor.done(); 138 } 139 140 private void linkLoggerLibrary(String loggingImpl, IProgressMonitor monitor) 141 { 142 if (! LoggingPlugin.LOGGING_PREFS_API_JDK_1_4.equals(loggingImpl)) 143 { 144 String name = LoggingPluginMessages.bind(LOGGING_LIB_PATHVAR + loggingImpl); 145 IClasspathEntry variableEntry = JavaCore.newVariableEntry(new Path(name), null, null, true); 146 147 IFileEditorInput input = (IFileEditorInput) _editor.getEditorInput(); 148 IProject project = input.getFile().getProject(); 149 IJavaProject javaProject = JavaCore.create(project); 150 try 151 { 152 IClasspathEntry[] classpathEntries = javaProject.getRawClasspath(); 153 IClasspathEntry[] newEntries = new IClasspathEntry[classpathEntries.length + 1]; 154 System.arraycopy(classpathEntries, 0 , newEntries, 0, classpathEntries.length); 155 newEntries[newEntries.length - 1] = variableEntry; 156 javaProject.setRawClasspath(newEntries, monitor); 157 } 158 catch (JavaModelException e) 159 { 160 if (e.getMessage().indexOf(DUPLICATE) < 0) 161 { 162 _logger.error("Error adding library", e); 163 } 164 } 165 166 } 167 } 168 169 private void addLoggerImports(String loggingImpl) throws JavaModelException 170 { 171 String imports = LoggingPluginMessages.bind(LOGGING_IMPORT_CLASS + loggingImpl); 172 StringTokenizer tokenizer = new StringTokenizer(imports, " ,"); 173 while (tokenizer.hasMoreTokens()) 174 { 175 _unit.createImport(tokenizer.nextToken(), null, null); 176 } 177 } 178 179 private void addLoggerField(String loggingImpl, String lineDelimiter, int tabWidth) throws JavaModelException 180 { 181 IType[] types = _unit.getTypes(); 182 if (types.length > 0) 183 { 184 IType type = types[0]; 185 int indentLevel = getIndentationLevel(type, tabWidth) + 1; 186 187 String field = LoggingPluginMessages.bind( 188 LOGGING_FIELD_DECLARATION + loggingImpl, 189 LoggingPlugin.getPlugin().getFieldNamePreference(), 190 type.getElementName() 191 ); 192 193 String formattedField = formatStatement(field + lineDelimiter, lineDelimiter, indentLevel); 194 195 try 196 { 197 type.createField(formattedField, null, false, null); 198 } 199 catch (JavaModelException e) 200 { 201 // name collisions should be ignored - if a field already exists, do not fail 202 if (e.getMessage().indexOf(EXISTS) < 0) 203 { 204 _logger.error("Failed to add field", e); 205 } 206 } 207 } 208 } 209 210 private void addLoggingStatement(String loggingImpl, IDocument document, String lineDelimiter, int tabWidth) 211 { 212 try 213 { 214 ITextSelection selection = (ITextSelection) _editor.getSelectionProvider().getSelection(); 215 int offset = selection.getOffset(); 216 IRegion lineInfo = document.getLineInformationOfOffset(offset); 217 int lineOffset = lineInfo.getOffset(); 218 int lineLength = lineInfo.getLength(); 219 int indentLevel = getIndentationLevel(document.get(lineOffset, lineLength), tabWidth); 220 int eolOffset = lineOffset + lineLength; 221 document.replace(eolOffset, 0, lineDelimiter); 222 223 String statement = null; 224 if (_action.isConditionalUsed()) 225 { 226 statement = _action.getConditionalLoggingStatement(loggingImpl); 227 } 228 else 229 { 230 statement = _action.getLoggingStatement(loggingImpl); 231 } 232 233 String formatterStatement = formatStatement(statement, lineDelimiter, indentLevel); 234 235 // append the formatted logging statement to this line 236 document.replace(eolOffset + lineDelimiter.length(), 0, formatterStatement); 237 } 238 catch (BadLocationException ignore) 239 { 240 } 241 } 242 243 private String formatStatement(String statement, String lineDelimiter, int indentLevel) 244 { 245 ICodeFormatter formatter = ToolFactory.createDefaultCodeFormatter(null); 246 return formatter.format(statement, indentLevel, null, lineDelimiter); 247 } 248 249 private String getLineDelimiter(IDocument document) 250 { 251 String delim = null; 252 try 253 { 254 delim = document.getLineDelimiter(0); 255 } 256 catch (BadLocationException e) 257 { 258 String[] delims = document.getLegalLineDelimiters(); 259 if (delims.length > 0) 260 { 261 delim = delims[0]; 262 } 263 if (delim == null) 264 { 265 delim = System.getProperty("line.separator", "\n"); 266 } 267 } 268 return delim; 269 } 270 271 private int getIndentationLevel(IType type, int tabWidth) 272 { 273 try 274 { 275 IBuffer buf = _unit.getBuffer(); 276 int offset = type.getSourceRange().getOffset(); 277 int count = 0; 278 int blanks = 0; 279 while (offset > 0) 280 { 281 char ch = buf.getChar(offset--); 282 switch (ch) 283 { 284 case '\t' : 285 ++count; 286 blanks = 0; 287 break; 288 case ' ' : 289 if (++blanks == tabWidth) 290 { 291 ++count; 292 blanks = 0; 293 } 294 break; 295 default : 296 return count; 297 } 298 } 299 return count; 300 } 301 catch (JavaModelException e) 302 { 303 return 0; 304 } 305 } 306 307 private int getIndentationLevel(String line, int tabWidth) 308 { 309 int count = 0; 310 int blanks = 0; 311 int length = line.length(); 312 for (int i = 0; i < length; i++) 313 { 314 char ch = line.charAt(i); 315 switch (ch) 316 { 317 case '\t' : 318 ++count; 319 blanks = 0; 320 break; 321 case ' ' : 322 if (++blanks == tabWidth) 323 { 324 ++count; 325 blanks = 0; 326 } 327 break; 328 default : 329 return count; 330 } 331 } 332 return count; 333 } 334 335 private int getTabWidth() 336 { 337 return Integer.parseInt(JavaCore.getOption(JavaCore.FORMATTER_TAB_SIZE)); 338 } 339 }

This page was automatically generated by Maven