Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package ext.org.eclipse.jdt.internal.ui.actions; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.text.ITextSelection; import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.IWorkingSet; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IImportDeclaration; import org.eclipse.jdt.core.IInitializer; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.ui.IWorkingCopyManager; import patch.org.eclipse.jdt.ui.actions.SelectionDispatchAction; import patch.org.eclipse.jdt.internal.ui.JavaPlugin; import ext.org.eclipse.jdt.internal.corext.refactoring.nls.NLSHintHelper; import ext.org.eclipse.jdt.internal.corext.refactoring.nls.NLSRefactoring; import ext.org.eclipse.jdt.internal.ui.browsing.LogicalPackage; import ext.org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import ext.org.eclipse.jdt.internal.ui.refactoring.nls.search.SearchBrokenNLSKeysUtil; import ext.org.eclipse.jdt.internal.ui.workingsets.IWorkingSetIDs; public class FindBrokenNLSKeysAction extends SelectionDispatchAction { private static class SearchPatternData { private final IType fAccessorType; private final IFile fPropertyFile; public SearchPatternData(IType accessorType, IFile propertyFile) { fAccessorType = accessorType; fPropertyFile = propertyFile; } public IFile getPropertyFile() { return fPropertyFile; } public IType getWrapperClass() { return fAccessorType; } } //TODO: Add to API: IJavaEditorActionDefinitionIds public static final String FIND_BROKEN_NLS_KEYS_ACTION_ID = "org.eclipse.jdt.ui.edit.text.java.find.broken.nls.keys"; //$NON-NLS-1$ //TODO: Add to API: JdtActionConstants public static final String ACTION_HANDLER_ID = "org.eclipse.jdt.ui.actions.FindNLSProblems"; //$NON-NLS-1$ private static final String JAVA_LANG_STRING = "QString;"; //$NON-NLS-1$ private JavaEditor fEditor; public FindBrokenNLSKeysAction(IWorkbenchSite site) { super(site); setText(ActionMessages.FindNLSProblemsAction_Name); setToolTipText(ActionMessages.FindNLSProblemsAction_ToolTip); setDescription(ActionMessages.FindNLSProblemsAction_Description); } /** * Note: This constructor is for internal use only. Clients should not call this constructor. * @param editor the Java editor */ public FindBrokenNLSKeysAction(JavaEditor editor) { this(editor.getEditorSite()); fEditor = editor; setEnabled(getCompilationUnit(editor) != null); } /* (non-Javadoc) * Method declared on SelectionDispatchAction. */ @Override public void run(ITextSelection selection) { ISelectionProvider selectionProvider = fEditor.getSelectionProvider(); if (selectionProvider == null) return; run(new StructuredSelection(selectionProvider.getSelection())); } /* (non-Javadoc) * Method declared on SelectionDispatchAction. */ @Override public void run(IStructuredSelection selection) { if (selection.size() == 1) { Object firstElement = selection.getFirstElement(); if (firstElement instanceof IJavaElement) { IJavaElement javaElement = (IJavaElement) firstElement; if (!ActionUtil.isProcessable(getShell(), javaElement)) { return; } } } SearchPatternData[] data = getNLSFiles(selection); if (data == null || data.length == 0) { MessageDialog.openInformation(getShell(), ActionMessages.FindNLSProblemsAction_ErrorDialogTitle, ActionMessages.FindNLSProblemsAction_NoPropertieFilesFoundErrorDescription); return; } String scope = "workspace"; //$NON-NLS-1$ if (selection.size() == 1) { Object firstElement = selection.getFirstElement(); if (firstElement instanceof IJavaElement) { scope = ((IJavaElement) firstElement).getElementName(); } else if (firstElement instanceof IFile) { scope = ((IFile) firstElement).getName(); } else if (firstElement instanceof IFolder) { scope = ((IFolder) firstElement).getName(); } } run(data, scope); } private void run(SearchPatternData[] data, String scope) { List<IType> wrappers = new ArrayList<IType>(); List<IFile> properties = new ArrayList<IFile>(); for (int i = 0; i < data.length; i++) { SearchPatternData current = data[i]; if (current.getWrapperClass() != null || current.getPropertyFile() != null) { wrappers.add(current.getWrapperClass()); properties.add(current.getPropertyFile()); } } IType[] accessorClasses = wrappers.toArray(new IType[wrappers.size()]); IFile[] propertieFiles = properties.toArray(new IFile[properties.size()]); SearchBrokenNLSKeysUtil.search(scope, accessorClasses, propertieFiles); } /* (non-Javadoc) * Method declared on SelectionDispatchAction. */ @Override public void selectionChanged(ITextSelection selection) { ISelectionProvider selectionProvider = fEditor.getSelectionProvider(); if (selectionProvider == null) { setEnabled(false); } else { selectionChanged(new StructuredSelection(selectionProvider.getSelection())); } } /* (non-Javadoc) * Method declared on SelectionDispatchAction. */ @Override public void selectionChanged(IStructuredSelection selection) { setEnabled(canEnable(selection)); } private SearchPatternData[] getNLSFiles(IStructuredSelection selection) { Object[] selectedElements = selection.toArray(); HashMap<IType, SearchPatternData> result = new HashMap<IType, SearchPatternData>(); collectNLSFilesFromResources(selectedElements, result); collectNLSFilesFromJavaElements(selectedElements, result); Collection<SearchPatternData> values = result.values(); return values.toArray(new SearchPatternData[values.size()]); } private boolean canEnable(IStructuredSelection selection) { Object[] selected = selection.toArray(); for (int i = 0; i < selected.length; i++) { try { if (selected[i] instanceof IJavaElement) { IJavaElement elem = (IJavaElement) selected[i]; if (elem.exists()) { switch (elem.getElementType()) { case IJavaElement.TYPE: if (elem.getParent().getElementType() == IJavaElement.COMPILATION_UNIT) { return true; } return false; case IJavaElement.COMPILATION_UNIT: return true; case IJavaElement.IMPORT_CONTAINER: return false; case IJavaElement.PACKAGE_FRAGMENT: case IJavaElement.PACKAGE_FRAGMENT_ROOT: IPackageFragmentRoot root = (IPackageFragmentRoot) elem .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); return (root.getKind() == IPackageFragmentRoot.K_SOURCE); case IJavaElement.JAVA_PROJECT: return true; } } } else if (selected[i] instanceof LogicalPackage) { return true; } else if (selected[i] instanceof IFile) { IFile file = (IFile) selected[i]; if ("properties".equalsIgnoreCase(file.getFileExtension())) //$NON-NLS-1$ return true; } else if (selected[i] instanceof IWorkingSet) { IWorkingSet workingSet = (IWorkingSet) selected[i]; return IWorkingSetIDs.JAVA.equals(workingSet.getId()); } } catch (JavaModelException e) { if (!e.isDoesNotExist()) { JavaPlugin.log(e); } } } return false; } private void collectNLSFilesFromResources(Object[] objects, HashMap<IType, SearchPatternData> result) { try { for (int i = 0; i < objects.length; i++) { Object object = objects[i]; IResource resource = null; if (object instanceof IWorkingSet) { IWorkingSet workingSet = (IWorkingSet) object; collectNLSFilesFromResources(workingSet.getElements(), result); } else if (object instanceof IJavaElement) { resource = ((IJavaElement) object).getCorrespondingResource(); } else if (object instanceof IResource) { resource = (IResource) object; } else if (object instanceof LogicalPackage) { LogicalPackage logicalPackage = (LogicalPackage) object; resource = logicalPackage.getJavaProject().getProject(); } if (resource instanceof IContainer) { collectNLSFilesFromResources(((IContainer) resource).members(), result); } else if (resource instanceof IFile) { SearchPatternData data = tryIfPropertyFileSelected((IFile) resource); if (data != null && !result.containsKey(data.fAccessorType)) { result.put(data.fAccessorType, data); } } } } catch (JavaModelException e) { if (!e.isDoesNotExist()) { JavaPlugin.log(e); } } catch (CoreException e) { JavaPlugin.log(e); } } private void collectNLSFilesFromJavaElements(Object[] objects, HashMap<IType, SearchPatternData> result) { try { for (int i = 0; i < objects.length; i++) { if (objects[i] instanceof IJavaElement) { IJavaElement elem = (IJavaElement) objects[i]; if (elem.exists()) { switch (elem.getElementType()) { case IJavaElement.TYPE: if (elem.getParent().getElementType() == IJavaElement.COMPILATION_UNIT) { ICompilationUnit unit = (ICompilationUnit) elem.getParent(); IType[] types = unit.getTypes(); if (types.length > 0 && !result.containsKey(types[0])) { SearchPatternData data = tryIfPropertyCuSelected(unit); if (data != null) result.put(data.fAccessorType, data); } } break; case IJavaElement.COMPILATION_UNIT: ICompilationUnit unit = (ICompilationUnit) elem; IType[] types = unit.getTypes(); if (types.length > 0 && !result.containsKey(types[0])) { SearchPatternData data = tryIfPropertyCuSelected(unit); if (data != null) result.put(data.fAccessorType, data); } break; case IJavaElement.PACKAGE_FRAGMENT: IPackageFragment fragment = (IPackageFragment) elem; if (fragment.getKind() == IPackageFragmentRoot.K_SOURCE) collectNLSFilesFromJavaElements(fragment.getChildren(), result); break; case IJavaElement.PACKAGE_FRAGMENT_ROOT: { IPackageFragmentRoot root = (IPackageFragmentRoot) elem; if (root.getKind() == IPackageFragmentRoot.K_SOURCE) collectNLSFilesFromJavaElements(root.getChildren(), result); break; } case IJavaElement.JAVA_PROJECT: { IJavaProject javaProject = (IJavaProject) elem; IPackageFragmentRoot[] allPackageFragmentRoots = javaProject .getAllPackageFragmentRoots(); for (int j = 0; j < allPackageFragmentRoots.length; j++) { IPackageFragmentRoot root = allPackageFragmentRoots[j]; if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { if (javaProject.equals(root.getJavaProject())) { collectNLSFilesFromJavaElements(new Object[] { root }, result); } } } break; } } } } else if (objects[i] instanceof LogicalPackage) { LogicalPackage logicalPackage = (LogicalPackage) objects[i]; collectNLSFilesFromJavaElements(new Object[] { logicalPackage.getJavaProject() }, result); } else if (objects[i] instanceof IWorkingSet) { IWorkingSet workingSet = (IWorkingSet) objects[i]; collectNLSFilesFromJavaElements(workingSet.getElements(), result); } } } catch (JavaModelException e) { if (!e.isDoesNotExist()) { JavaPlugin.log(e); } } } private SearchPatternData tryIfPropertyCuSelected(ICompilationUnit compilationUnit) throws JavaModelException { if (compilationUnit == null) return null; if (!ActionUtil.isOnBuildPath(compilationUnit)) return null; IType[] types = compilationUnit.getTypes(); if (types.length != 1) return null; if (!isPotentialNLSAccessor(compilationUnit)) return null; IStorage bundle = NLSHintHelper.getResourceBundle(compilationUnit); if (!(bundle instanceof IFile)) return null; return new SearchPatternData(types[0], (IFile) bundle); } /* * Be conservative, for every unit this returns true an AST will to be created! */ private static boolean isPotentialNLSAccessor(ICompilationUnit unit) throws JavaModelException { IType type = unit.getTypes()[0]; if (!type.exists()) return false; IField bundleNameField = getBundleNameField(type.getFields()); if (bundleNameField == null) return false; if (importsOSGIUtil(unit)) { //new school IInitializer[] initializers = type.getInitializers(); for (int i = 0; i < initializers.length; i++) { if (Modifier.isStatic(initializers[0].getFlags())) return true; } } else { //old school IMethod[] methods = type.getMethods(); for (int i = 0; i < methods.length; i++) { IMethod method = methods[i]; if (isValueAccessor(method)) return true; } } return false; } private static boolean importsOSGIUtil(ICompilationUnit unit) throws JavaModelException { IImportDeclaration[] imports = unit.getImports(); for (int i = 0; i < imports.length; i++) { if (imports[i].getElementName().startsWith("org.eclipse.osgi.util.")) //$NON-NLS-1$ return true; } return false; } private static boolean isValueAccessor(IMethod method) throws JavaModelException { if (!"getString".equals(method.getElementName())) //$NON-NLS-1$ return false; int flags = method.getFlags(); if (!Modifier.isStatic(flags) || !Modifier.isPublic(flags)) return false; String returnType = method.getReturnType(); if (!JAVA_LANG_STRING.equals(returnType)) return false; String[] parameters = method.getParameterTypes(); if (parameters.length != 1 || !JAVA_LANG_STRING.equals(parameters[0])) return false; return true; } private static IField getBundleNameField(IField[] fields) { for (int i = 0; i < fields.length; i++) { if ("BUNDLE_NAME".equals(fields[i].getElementName())) //$NON-NLS-1$ return fields[i]; } return null; } private SearchPatternData tryIfPropertyFileSelected(IFile file) { if (!"properties".equalsIgnoreCase(file.getFileExtension())) //$NON-NLS-1$ return null; IPath propertyFullPath = file.getFullPath(); // Try to find a corresponding CU String[] javaExtensions = JavaCore.getJavaLikeExtensions(); for (int i = 0; i < javaExtensions.length; i++) { String extension = javaExtensions[i]; IPath cuPath = propertyFullPath.removeFileExtension().addFileExtension(extension); IFile cuFile = (IFile) JavaPlugin.getWorkspace().getRoot().findMember(cuPath); if (cuFile == null) { //try with uppercase first char String filename = cuPath.removeFileExtension().lastSegment(); if (filename != null && filename.length() > 0) { filename = Character.toUpperCase(filename.charAt(0)) + filename.substring(1); IPath dirPath = propertyFullPath.removeLastSegments(1).addTrailingSeparator(); cuPath = dirPath.append(filename).addFileExtension(extension); cuFile = (IFile) JavaPlugin.getWorkspace().getRoot().findMember(cuPath); } } if (cuFile != null && cuFile.exists()) { IJavaElement element = JavaCore.create(cuFile); if (element != null && element.exists() && element.getElementType() == IJavaElement.COMPILATION_UNIT && ActionUtil.isOnBuildPath(element)) { ICompilationUnit compilationUnit = (ICompilationUnit) element; IType type = compilationUnit.findPrimaryType(); if (type != null) { String resourceBundleName = NLSHintHelper.getResourceBundleName(compilationUnit); if (resourceBundleName != null) { String resourceName = resourceBundleName + NLSRefactoring.PROPERTY_FILE_EXT; String name = file.getName(); if (resourceName.endsWith(name)) { return new SearchPatternData(type, file); } } } } } } return null; } private static ICompilationUnit getCompilationUnit(JavaEditor editor) { IWorkingCopyManager manager = JavaPlugin.getDefault().getWorkingCopyManager(); ICompilationUnit cu = manager.getWorkingCopy(editor.getEditorInput()); return cu; } }