Java tutorial
/* * Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved. * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License, Version 1.0, * which accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html * */ package net.rim.ejde.internal.util; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import net.rim.ejde.internal.core.IConstants; import net.rim.ide.JavaParser; import net.rim.ide.Project; import net.rim.sdk.rc.ConvertUtil; import net.rim.sdk.rc.ResourceCollection; import net.rim.sdk.rc.parser.ResourceHeaderParser; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.core.JavaModel; import org.eclipse.osgi.util.NLS; /** * A utility class to construct/retrieve package informations. * * @author Raj Gunaratnam * @since 11 December, 08 */ public class PackageUtils implements net.rim.ejde.internal.core.IConstants { private static final Logger _logger = Logger.getLogger(PackageUtils.class); /** * Get the package name of the given <code>rrhFile</code>. * <p> * The returned package is in <code>com/rim/test</code> format. * </p> * * @param rrhFile * @return packageId String or <code>null</code> if the given file is null or the given file is not a rrh file * @throws CoreException */ public static String getRRHPackageString(File rrhFile) throws CoreException { String packageName = getRRHPackageID(rrhFile); if (!StringUtils.isBlank(packageName)) { packageName = convertPkgIDToString(packageName); } return packageName; } /** * Get the file name of corresponding rrh file for the given <code>rrcFile</code>. * * @param rrcFile * @return rrhFile */ public static File getCorrespondingRRHFile(File rrcFile) { if (rrcFile == null) { return null; } IPath rrcPath = new Path(rrcFile.getPath()); String extension = rrcPath.getFileExtension(); if ((extension == null) || !extension.equalsIgnoreCase(RRC_FILE_EXTENSION)) { return null; } String fileName = rrcFile.getName(); if (fileName.contains("_")) { fileName = fileName.substring(0, fileName.indexOf('_')); } else { fileName = fileName.substring(0, fileName.indexOf(DOT_CHAR)); } fileName += RRH_FILE_EXTENSION_WITH_DOT; IPath rrhPath = rrcPath.removeLastSegments(1); rrhPath = rrhPath.append(fileName); return rrhPath.toFile(); } /** * Get the package string of the given <code>rrcFile</code>. * <p> * The returned package is in <code>com/rim/test</code> format. * </p> * * @param rrcFile * File * @return packageId String or <code>null</code> if the given file is null or the given file is not a rrc file * @throws CoreException */ public static String getRRCPackageString(File rrcFile) throws CoreException { String packageId; packageId = getRRCPackageID(rrcFile); if (!StringUtils.isBlank(packageId)) { packageId = convertPkgIDToString(packageId); } return packageId; } /** * Get the package id of the given <code>rrcFile</code>. * <p> * The returned package is in <code>com.rim.test</code> format. * </p> * * @param rrcFile * File * @return packageId String or <code>null</code> if the given file is null or the given file is not a rrc file * @throws CoreException */ public static String getRRCPackageID(File rrcFile) throws CoreException { if (rrcFile == null) { return null; } if (!rrcFile.getName().endsWith(RRC_FILE_EXTENSION_WITH_DOT)) { return null; } String packageId = null; File rrhFile = getCorrespondingRRHFile(rrcFile); if (rrhFile != null) { try { packageId = getRRHPackageID(rrhFile); } catch (CoreException e) { throw new CoreException(StatusFactory.createErrorStatus( NLS.bind(Messages.PackageUtils_RELATED_RRH_FILE_ERROR_MESSAGE, rrcFile.getPath()))); } } return packageId; } /** * Get the package id of the given <code>rrhFile</code>. * <p> * The returned package is in <code>com.rim.test</code> format. * </p> * * @param rrhFile * File * @return packageId String or <code>null</code> if the given file is null or the given file is not a rrh file * @throws CoreException */ public static String getRRHPackageID(File rrhFile) throws CoreException { if (rrhFile == null) { return null; } if (!rrhFile.getName().endsWith(RRH_FILE_EXTENSION_WITH_DOT)) { return null; } if (!rrhFile.exists()) { throw new CoreException(StatusFactory .createErrorStatus(NLS.bind(Messages.PackageUtils_RRH_FILE_NOT_EXIST, rrhFile.toString()))); } String fileStringPath = rrhFile.getPath(); ResourceCollection collection = new ResourceCollection( fileStringPath.substring(0, fileStringPath.length() - 4)); ResourceHeaderParser parser = null; String packageName = null; try { parser = new ResourceHeaderParser(fileStringPath, collection); parser.read(); } catch (IOException e) { _logger.error(NLS.bind(Messages.PackageUtils_PACKAGE_ID_ERROR_MSG, rrhFile.toString())); throw new CoreException(StatusFactory.createErrorStatus( NLS.bind(Messages.PackageUtils_PACKAGE_ID_ERROR_MSG, rrhFile.toString()), e)); } packageName = collection.getPackage(); return packageName; } /** * Get the package string of the given <code>imgFile</code> within given <code>eclipseProject</code>. This method will * calculate package id based on the JDP file location. This method can be used for any non java, non rrh and non rrc files * package calculation. * <p> * The returned package is in <code>com/rim/test</code> format. * </P> * * @param file * File * @return packageId String */ static public String buildGenaralFilePackageString(File file, Project legacyProject) { IPath filePath = null; String pathAlias = EMPTY_STRING; if ((file == null)) { throw new IllegalArgumentException( NLS.bind(Messages.PackageUtils_UNDEFINED_FILE_ERROR_MSG, IConstants.EMPTY_STRING)); } if (file.getName().endsWith(JAVA_EXTENSION_WITH_DOT) || file.getName().endsWith(RRC_FILE_EXTENSION_WITH_DOT) || file.getName().endsWith(RRH_FILE_EXTENSION_WITH_DOT)) { throw new IllegalArgumentException("This method doesn't process java/rrh/rrc files!"); } filePath = new Path(file.getPath()); if (legacyProject != null) { IPath bbwkspath = (new Path(legacyProject.getWorkspace().getFile().toString())).removeLastSegments(1); IPath bbprjpath = (new Path(legacyProject.getFile().toString())).removeLastSegments(1); // remove the file name segment IPath resolvedPath = resolvePathForFile(filePath, bbprjpath, bbwkspath).removeLastSegments(1); List<String> sources = ImportUtils.getSources(legacyProject); String firstSegment = resolvedPath.segment(0); if (sources.contains(firstSegment)) { resolvedPath = resolvedPath.removeFirstSegments(1); } pathAlias = resolvedPath.toString(); } return pathAlias;// com/rim/test } /** * Deresolves a file path 1st referred to a project path, then to a workspace path or flatten if completely outside * * @param file * @param projectPath * @param workspacePath * @return */ public static IPath resolvePathForFile(IPath filePath, IPath projectPath, IPath workspacePath) { IPath deresolvedPath = deResolve(filePath, projectPath); if (deresolvedPath.isAbsolute() || DOUBLE_DOTS.equals(deresolvedPath.segment(0))) { deresolvedPath = deResolve(filePath, workspacePath); if (deresolvedPath.isAbsolute() || DOUBLE_DOTS.equals(deresolvedPath.segment(0))) { deresolvedPath = new Path(filePath.lastSegment()); } } return deresolvedPath; } /** * Return the absolute path of the given entry. * * @param currentEntry * @return the absolute path of the give entry. Return <code>null<code> if the entry can not be found. */ public static IPath getAbsolutePath(IClasspathEntry currentEntry) { if (currentEntry == null) { return null; } if (currentEntry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) { return currentEntry.getPath(); } IPath absolutePath = null; IPath path = currentEntry.getPath(); Object target = JavaModel.getTarget(path, true); if (target instanceof IResource) { // if the target was found inside workspace IResource resource = (IResource) target; absolutePath = resource.getLocation(); } else if (target instanceof File) { // if the target was found outside of the workspace absolutePath = new Path(((File) target).getAbsolutePath()); } return absolutePath; } /** * @deprecatated Use {@link getAbsolutePath(IClasspathEntry)} instead */ public static IPath getAbsoluteEntryPath(IClasspathEntry currentEntry) { return getAbsolutePath(currentEntry); } /** * De-resolves a path vs a base path Example: path --> C:\workspace\myProject\com\rim\test\a.JPG base --> * C:\workspace\myProject\P1.jdp return path --> com/rim/test/a.JPG -- relative to JDP * * @param path * IPath * @param base * IPath * @return path IPath */ public static IPath deResolve(IPath path, IPath base) { IPath modfiedBase = base; if (modfiedBase.toFile().isFile()) { modfiedBase = modfiedBase.removeLastSegments(1); } int mn = modfiedBase.matchingFirstSegments(path); if (mn > 0) { IPath dpath = path.setDevice(EMPTY_STRING).removeFirstSegments(mn); int nj = modfiedBase.segmentCount() - mn; // TODO: Try using forward slash as a path separator in Windows String str = DOUBLE_DOTS + File.separator; IPath tempPath = new Path(str); for (int i = 0; i < nj; i++) { dpath = tempPath.append(dpath); } return dpath; } return path; // com/rim/test/a.JPG } /** * Gets all the source folders of the given <code>iJavaProject</code>. * * @param iJavaProject * @return */ public static ArrayList<IContainer> getAllSrcFolders(IJavaProject iJavaProject) { ArrayList<IContainer> result = new ArrayList<IContainer>(); IProject iProject = iJavaProject.getProject(); IClasspathEntry[] classPathEntries = null; IFolder srcFolder = null; IPath srcFolderPath = null; IPath relativeSrcFolderPath = null; try { classPathEntries = iJavaProject.getRawClasspath(); for (IClasspathEntry classPathEntry : classPathEntries) { if (classPathEntry.getEntryKind() != IClasspathEntry.CPE_SOURCE) { continue; } srcFolderPath = classPathEntry.getPath(); if (srcFolderPath.segment(0).equals(iProject.getName())) { // remove the project name from the path relativeSrcFolderPath = srcFolderPath.removeFirstSegments(1); } if (relativeSrcFolderPath == null || relativeSrcFolderPath.isEmpty()) { result.add(iProject); } else { srcFolder = iProject.getFolder(relativeSrcFolderPath); if (srcFolder.exists()) { result.add(srcFolder); } } } } catch (Throwable e) { _logger.error(e.getMessage(), e); } return result; } /** * This method will retrieves the list of non derived source folders of the given <code>iJavaProject</code>. * * @param iJavaProject * IJavaProject * @return result ArrayList<IFolder> */ public static ArrayList<IContainer> getNonDerivedSrcFolders(IJavaProject iJavaProject) { ArrayList<IContainer> result = getAllSrcFolders(iJavaProject); ArrayList<IContainer> newResult = new ArrayList<IContainer>(); for (IContainer container : result) { if (!container.isDerived()) { newResult.add(container); } } return newResult; } /** * This method will retrieves the 1st source-folder other than src if multiple * * @param iJavaProject * @return <IFolder> srcFolder or null if no source-folders */ public static IContainer getSrcFolderForNonPackage(IJavaProject iJavaProject) { ArrayList<IContainer> srcFolders = getNonDerivedSrcFolders(iJavaProject); for (IContainer srcFolder : srcFolders) { if ("src".equals(srcFolder.getName()) && (srcFolders.size() > 1)) { continue; } return srcFolder; } return null; } /** * This method will return true if the given resource is under any source folders * * @param resource * IResource * @return found Boolean */ public static boolean isUnderSrcFolder(IResource resource) { boolean found = false; IPath path = resource.getFullPath(); IProject iProject = resource.getProject(); IJavaProject iJavaProject = JavaCore.create(iProject); ArrayList<IContainer> srcc = PackageUtils.getAllSrcFolders(iJavaProject); for (IContainer srcFolder : srcc) { IPath p = srcFolder.getFullPath(); if (p.isPrefixOf(path) || path.isPrefixOf(p)) { found = true; break; } } return found; } /** * This method will return true if the resource represented by the given <code>path</code> is under/linked to any source * folders of the <code>eclipseJavaProject</code>. * * @param eclipseJavaProject * IJavaProject * @param path * IPath * * @return */ public static boolean isUnderSrcFolder(IJavaProject eclipseJavaProject, IPath path) { List<IContainer> srcc = PackageUtils.getAllSrcFolders(eclipseJavaProject); IPath p; for (IContainer srcFolder : srcc) { p = srcFolder.getLocation(); if (p.isPrefixOf(path)) { return true; } else { // continue to check if the resource represented by the path is linked to the project FileSearchVisitor visitor = new FileSearchVisitor(path); try { srcFolder.accept(visitor); } catch (CoreException e) { _logger.error(e.getMessage()); return false; } if (visitor.found()) { return true; } } } return false; } static private class FileSearchVisitor implements IResourceVisitor { IPath _path; boolean _found; public FileSearchVisitor(IPath path) { _path = path; _found = false; } @Override public boolean visit(IResource resource) throws CoreException { if (_found) { return false; } if (!(resource instanceof IFile)) { return true; } if (resource.getLocation().equals(_path)) { _found = true; } return false; } public boolean found() { return _found; } } /** * Get the project relative path of the resource represented by the given <code>filePath</code>. The <code>filePath</code> is * a path which contains package and file name. * * @param javaProject * @param filePath * @return Project relative path which contains source folder/package/filename, e.g. src/net/rim/api/a.java. * <p> * or <code>null</code> if the filepath does not exist in the project. */ public static IPath getProjectRelativePath(IJavaProject javaProject, IPath filePath) { List<IContainer> srcc = PackageUtils.getNonDerivedSrcFolders(javaProject); IPath p; IFile iFile; for (IContainer srcFolder : srcc) { p = new Path(srcFolder.getName()).append(filePath); iFile = javaProject.getProject().getFile(p); if (iFile.exists()) { return p; } } return null; } /** * This method will return the source folder in which the given <code>resource</code> is located. * * @param resource * IResource * @return the source folder in which the given <code>resource</code> is located or <code>null</code> if the given * <code>resource</code> is not located in any source folder */ public static IContainer getSrcFolder(IResource resource) { IPath path = resource.getFullPath(); IProject iProject = resource.getProject(); IJavaProject iJavaProject = JavaCore.create(iProject); ArrayList<IContainer> srcFolders = getNonDerivedSrcFolders(iJavaProject); for (IContainer srcFolder : srcFolders) { IPath p = srcFolder.getFullPath(); if (p.isPrefixOf(path)) { return srcFolder; } } return null; } /** * Get package string for java file in <code>com/rim/test</code> format. * * @param file * File * @return packageId String */ public static String getJavaFilePackageString(File file) { String packageId = getJavaFilePackageID(file); if (!StringUtils.isBlank(packageId)) { packageId = convertPkgIDToString(packageId); } return packageId; // com/rim/test } /** * Get package id for java file in com.rim.test format * * @param file * File * @return packageId String */ public static String getJavaFilePackageID(File file) { String packageId = EMPTY_STRING; if (file == null) { return EMPTY_STRING; } try { FileReader fileReader = new FileReader(file); JavaParser parser = new JavaParser(file, fileReader, true); packageId = parser.getPackage(); try { fileReader.close(); } catch (IOException ioe) { _logger.error(ioe); } return packageId; // com.rim.test } catch (FileNotFoundException fnfe) { return EMPTY_STRING; } } /** * Whether the given filename has a BB source type extension * * @param filename * @return */ public static boolean hasSourceExtension(String filename) { String filename_ = filename.toLowerCase(); return filename_.endsWith(JAVA_EXTENSION_WITH_DOT) || filename_.endsWith(RRH_FILE_EXTENSION_WITH_DOT) || filename_.endsWith(RRC_FILE_EXTENSION_WITH_DOT); } /** * Whether is a java file by extension * * @param filename * @return */ public static boolean hasJavaExtension(String filename) { return filename.toLowerCase().endsWith(JAVA_EXTENSION_WITH_DOT); } /** * Whether is a rrh file by extension * * @param filename * @return */ public static boolean hasRRHExtension(String filename) { return filename.toLowerCase().endsWith(RRH_FILE_EXTENSION_WITH_DOT); } /** * Whether is a rrc file by extension * * @param filename * @return */ public static boolean hasRRCExtension(String filename) { return filename.toLowerCase().endsWith(RRC_FILE_EXTENSION_WITH_DOT); } /** * A common method to get a relative file path w\ package string for given <code>File</code>. * <p> * The returned path is in <code>com/rim/test</code> format. * </p> * * @param file * @param legacyProject * @return package string * @throws IOException */ public static String getFilePackageString(File file, Project legacyProject) throws CoreException { String packageString; String fileName = file.getName(); if (fileName.endsWith(JAVA_EXTENSION_WITH_DOT)) { packageString = getJavaFilePackageString(file); } else if (fileName.endsWith(RRH_FILE_EXTENSION_WITH_DOT)) { packageString = getRRHPackageString(file); } else if (fileName.endsWith(RRC_FILE_EXTENSION_WITH_DOT)) { packageString = getRRCPackageString(file); } else { packageString = buildGenaralFilePackageString(file, legacyProject); } return packageString; } /** * This method will convert the package name (com.rim.test) into package id (exclusion pattern) format (com/rim/test) * * @param packageID * String * @return result String */ public static String convertPkgIDToString(String packageID) { String result = packageID; if (result == null) { return null; } result = packageID.replace(DOT_CHAR, File.separatorChar); return result;// my/net/rim } /** * This method will convert the package String (com/rim/test) into package id format (com.rim.test) * * @param packageString * String * @return result String */ public static String convertPkgStringToID(String packageString) { StringBuffer buf = new StringBuffer(); if (packageString == null) { return null; } IPath path = new Path(packageString); for (int i = 0; i < path.segmentCount(); i++) { if (i == 0) { buf.append(path.segment(i)); } else { buf.append(DOT_MARK + path.segment(i)); } } return buf.toString(); // com.rim.test } /** * Compose the crb file name based on the given <code>rrcFileNem</code> and <code>packageID</code>. The given * <code>rrcFileName</code> should not contain the file extension (.rrc). * * <p> * If the given <code>rrcFile</code> is resource_en_US and the given <code>packageID</code> is "net.rim.test", the returned * crb file name is <code>net.rim.test.resourceen_US.crb</code>. * </p> * * @param rrcFileName * @return */ public static String getCRBFileName(String rrcFileName, String packageID, boolean alt) { int index = rrcFileName.indexOf("_"); //$NON-NLS-1$ String crbFileName; if (index > 0) { String fileNameWithoutLocal = rrcFileName.substring(0, index); // get the locale string, e.g. en_us String localeString = rrcFileName.substring(index + 1); localeString = ConvertUtil.localeValueOf(localeString).toString().trim(); // resource_en_us --> resourceen_us if (alt) { localeString = convertAltLocale(localeString); } crbFileName = fileNameWithoutLocal + String.valueOf(ConvertUtil.LOCALE_SEPARATOR) + localeString; } else { crbFileName = rrcFileName + String.valueOf(ConvertUtil.LOCALE_SEPARATOR); } // append .crb extension crbFileName += CRB_EXTENSION_WITH_DOT; // add the package id if (!StringUtils.isBlank(packageID)) { crbFileName = packageID + DOT_CHAR + crbFileName; } return crbFileName; } private static String convertAltLocale(String localeString) { String altLocale = localeString; if (localeString.startsWith("iw")) { altLocale = "he" + localeString.substring(2); } else if (localeString.startsWith("in")) { altLocale = "id" + localeString.substring(2); } return altLocale; } public static void createFolder(IFolder folder) throws CoreException { if (!folder.exists()) { IContainer parent = folder.getParent(); if (parent instanceof IFolder) { createFolder((IFolder) parent); } folder.create(true, true, new NullProgressMonitor()); } } static public String parseFileForPackageId(File file) { if ((null == file) || file.isDirectory() || !file.exists()) { String msg = NLS.bind(Messages.PackageUtils_UNDEFINED_FILE_ERROR_MSG, IConstants.EMPTY_STRING); _logger.error(msg); throw new RuntimeException(msg); } String packageId = null, filePath = file.getAbsolutePath(), line, token; BufferedReader bufferedReader = null; StringTokenizer tokenizer; try { if (PackageUtils.hasRRHExtension(filePath) || PackageUtils.hasRRCExtension(filePath) || PackageUtils.hasJavaExtension(filePath)) { bufferedReader = new BufferedReader(new FileReader(file)); if (!bufferedReader.ready()) { throw new RuntimeException( NLS.bind(Messages.PackageUtils_EMPTY_FILE_ERROR_MSG, file.getPath())); } while (null != (line = bufferedReader.readLine())) { // pull lines from file till find the one containing // package definition line = line.trim(); if ((0 < line.length()) && // criterion to recognize a // package declaration line.startsWith("package")) { while (!line.contains(IConstants.SEMICOLON_MARK)) { line = line + bufferedReader.readLine(); } tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { // pull the package tokens token = tokenizer.nextToken(); if (!"package".equals(token)) { if (token.contains(IConstants.SEMICOLON_MARK)) { token = token.replaceAll(IConstants.SEMICOLON_MARK, IConstants.EMPTY_STRING); } packageId = StringUtils.isNotBlank(token) ? token : IConstants.EMPTY_STRING; break; } // end pulling of eventual package tokens } } if (null != packageId) { // file break; } } } else { throw new RuntimeException( NLS.bind(Messages.PackageUtils_UNSUPPORTED_FILE_ERROR_MSG, file.getPath())); } } catch (Throwable t) { _logger.debug(t.getMessage(), t); } finally { if (null != bufferedReader) { try { bufferedReader.close(); } catch (IOException e) { _logger.error(e.getMessage(), e); } } } return packageId; } }