/******************************************************************************* * Copyright (c) 2003, 2007 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 org.eclipse.jst.j2ee.internal.web.operations; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Vector; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jem.workbench.utility.JemProjectUtilities; import org.eclipse.jst.j2ee.internal.J2EEConstants; import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants; import org.eclipse.jst.j2ee.internal.project.ProjectSupportResourceHandler; import org.eclipse.jst.j2ee.internal.web.plugin.WebPlugin; import org.eclipse.wst.common.componentcore.ComponentCore; import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; import org.eclipse.wst.common.componentcore.resources.IVirtualFolder; import com.ibm.icu.text.UTF16; import com.ibm.icu.util.StringTokenizer; public class WebPropertiesUtil { // private static final char[] BAD_CHARS = {'/', '\\', ':'}; private static final char[] BAD_CHARS = {':'}; public static final String DEFAULT_JAVA_SOURCE_NAME = "Java Source"; //$NON-NLS-1$ //TODO Port to flexible structure /** * Update the Web Content folder to a new value if it is different. This applies to both Static * and J2EE Web Projects. In the case of a J2EE Project, the library classpath entries will be * modifies to reflect the new location. * * @param project * The Web Project to update * @param webContentName * The new name given to the Web Project's Web Content folder * @param progressMonitor * Indicates progress of the update operation * @return True if the web content rename was actually renamed, false if unneeded. * @throws CoreException * The exception that occured during renaming of the the project's web content * folder */ public static boolean updateWebContentNameAndProperties(IProject project, String webContentName, IProgressMonitor progressMonitor) throws CoreException { boolean success = false; if (project.exists() && project.isOpen()) { /* * IBaseWebNature webNature = J2EEWebNatureRuntimeUtilities.getRuntime(project); if * (webContentName == null) { if (webNature.isStatic()) { webContentName = * J2EEWebNatureRuntimeUtilities.getDefaultStaticWebContentName(); } else { * webContentName = J2EEWebNatureRuntimeUtilities.getDefaultJ2EEWebContentName(); } } */ IPath newPath = new Path(webContentName); if (getModuleServerRoot(project).getProjectRelativePath().equals(newPath)) return false; if (project.exists(newPath)) { IStatus status = new Status(IStatus.ERROR, "org.eclipse.jst.j2ee", IStatus.OK, ProjectSupportResourceHandler.getString(ProjectSupportResourceHandler.Could_not_rename_____2, new Object[]{webContentName}), null); //$NON-NLS-1$ throw new CoreException(status); } moveWebContentFolder(project, webContentName, progressMonitor); updateWebContentNamePropertiesOnly(project, webContentName, progressMonitor); success = true; } return success; } /** * Update the classpath entries and Server Root Name for this web project only. * * @param project * @param webContentName * @return */ public static void updateWebContentNamePropertiesOnly(IProject project, String webContentName, IProgressMonitor progressMonitor) throws CoreException { IPath newPath = new Path(webContentName); if (getModuleServerRoot(project).equals(newPath)) return; if (!getModuleServerRoot(project).equals(webContentName)) { // if (webModuleArtifact.isJ2EE) { // Update the library references IJavaProject javaProject = JemProjectUtilities.getJavaProject(project); IClasspathEntry[] classpath = javaProject.getRawClasspath(); IClasspathEntry[] newClasspath = new IClasspathEntry[classpath.length]; for (int i = 0; i < classpath.length; i++) { if (classpath[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IClasspathEntry library = classpath[i]; IPath libpath = library.getPath(); IPath modServerRootPath = getModuleServerRoot(project).getFullPath(); if (modServerRootPath.isPrefixOf(libpath)) { IPath prunedPath = libpath.removeFirstSegments(modServerRootPath.segmentCount()); IPath relWebContentPath = new Path(webContentName + "/" + prunedPath.toString()); //$NON-NLS-1$ IResource absWebContentPath = project.getFile(relWebContentPath); IPath srcAttachmentPath = library.getSourceAttachmentPath(); if (null != srcAttachmentPath) { prunedPath = srcAttachmentPath.removeFirstSegments(modServerRootPath.segmentCount()); } IResource absWebContentSrcAttachmentPath = project.getFile(relWebContentPath); newClasspath[i] = JavaCore.newLibraryEntry(absWebContentPath.getFullPath(), absWebContentSrcAttachmentPath.getFullPath(), library.getSourceAttachmentRootPath(), library.isExported()); } else { newClasspath[i] = classpath[i]; } } else { newClasspath[i] = classpath[i]; } // } // Set the java output folder IFolder outputFolder = project.getFolder(getModuleServerRoot(project).getFullPath()); javaProject.setRawClasspath(newClasspath, outputFolder.getFullPath(), new SubProgressMonitor(progressMonitor, 1)); } // update websettings // TODO add to WebArtifactEdit // webNature.setModuleServerRootName(webContentName); } } /** * Moves the web content folder to the name indicated only if that path doesn't already exist in * the project. * * @param project * The web project to be updated. * @param webContentName * The new web content name * @param progressMonitor * Indicates progress * @throws CoreException * The exception that occured during move operation */ public static void moveWebContentFolder(IProject project, String webContentName, IProgressMonitor progressMonitor) throws CoreException { IPath newPath = new Path(webContentName); if (!project.exists(newPath)) { if (newPath.segmentCount() > 1) { for (int i = newPath.segmentCount() - 1; i > 0; i--) { IPath tempPath = newPath.removeLastSegments(i); IFolder tempFolder = project.getFolder(tempPath); if (!tempFolder.exists()) { tempFolder.create(true, true, null); } } } newPath = project.getFullPath().append(newPath); IContainer webContentRoot = getModuleServerRoot(project); IPath oldPath = webContentRoot.getProjectRelativePath(); webContentRoot.move(newPath, IResource.FORCE | IResource.KEEP_HISTORY, new SubProgressMonitor(progressMonitor, 1)); for (int i = 0; i < oldPath.segmentCount(); i++) { IPath tempPath = oldPath.removeLastSegments(i); IFolder tempFolder = project.getFolder(tempPath); if (tempFolder.exists() && tempFolder.members().length == 0) { tempFolder.delete(true, true, null); } } } } /** * Synchonizies the class path and the lib directories to catch any changes from the last use * Creation date: (4/17/01 11:48:12 AM) */ protected static void synch(IProject project, IProgressMonitor monitor) { IProgressMonitor localMonitor = monitor; try { if (localMonitor == null) { localMonitor = new NullProgressMonitor(); } localMonitor.beginTask(ProjectSupportResourceHandler.Sychronize_Class_Path_UI_, 4); //$NON-NLS-1$ = "Sychronize Class Path" IContainer lib_folder = getWebLibFolder(project); // Nothing to do if the lib folder does not exist. if (lib_folder == null || !lib_folder.isAccessible()) return; IJavaProject javaProject = JemProjectUtilities.getJavaProject(project); IPath lib_path = lib_folder.getProjectRelativePath(); IPath lib_full_path = lib_folder.getFullPath(); IClasspathEntry[] cp = javaProject.getRawClasspath(); boolean needsToBeModified = false; // Create a map of the lib projects in the current project Hashtable lib_jars = new Hashtable(); IResource[] children = lib_folder.members(); localMonitor.subTask(ProjectSupportResourceHandler.Catalog_Lib_Directory__UI_); //$NON-NLS-1$ = "Catalog Lib Directory:" for (int j = 0; j < children.length; j++) { IResource child = children[j]; // monitor.setTaskName(ResourceHandler.getString("Catalog_Lib_Directory__UI_") + // child); //$NON-NLS-1$ = "Catalog Lib Directory:" // Make sure it is a zip or a jar file if (child.getType() == IResource.FILE && (child.getFullPath().toString().toLowerCase().endsWith(IJ2EEModuleConstants.JAR_EXT) || child.getFullPath().toString().toLowerCase().endsWith(".zip"))) { //$NON-NLS-1$ lib_jars.put(child.getFullPath(), child); } } localMonitor.worked(1); localMonitor.subTask(ProjectSupportResourceHandler.Update_ClassPath__UI_); //$NON-NLS-1$ = "Update ClassPath:" // Loop through all the classpath dirs looking for ones that may have // been deleted Vector newClassPathVector = new Vector(); for (int j = 0; j < cp.length; j++) { // If it is a lib_path if (cp[j].getPath().toString().startsWith(lib_path.toString()) || cp[j].getPath().toString().startsWith(lib_full_path.toString())) { // It was already in the class path if (lib_jars.get(cp[j].getPath()) != null) { newClassPathVector.add(cp[j]); // Remove it from the hash table of paths to add back // monitor.setTaskName(ResourceHandler.getString("Catalog_Lib_Directory__UI_") // + cp[j].getPath()); //$NON-NLS-1$ = "Catalog Lib Directory:" lib_jars.remove(cp[j].getPath()); } else { // You have removed something form the class path you // will need to re-build // monitor.setTaskName(ResourceHandler.getString("Catalog_Lib_Directory_Remo_UI_") // + cp[j].getPath()); //$NON-NLS-1$ = "Catalog Lib Directory:Remove " needsToBeModified = true; } } else { localMonitor.subTask(ProjectSupportResourceHandler.Catalog_Lib_Directory__UI_ + cp[j].getPath()); //$NON-NLS-1$ = "Catalog Lib Directory:" newClassPathVector.add(cp[j]); } } localMonitor.worked(1); localMonitor.subTask(ProjectSupportResourceHandler.Update_ClassPath__UI_); //$NON-NLS-1$ = "Update ClassPath:" // Add any entries not already found Enumeration aenum = lib_jars.keys(); while (aenum.hasMoreElements()) { IPath path = (IPath) aenum.nextElement(); newClassPathVector.add(JavaCore.newLibraryEntry(path, null, null)); // You have added something form the class path you // will need to re-build // monitor.setTaskName(ResourceHandler.getString("23concat_UI_", (new Object[] { // path }))); //$NON-NLS-1$ = "Catalog Lib Directory:Add {0}" needsToBeModified = true; } localMonitor.worked(1); localMonitor.subTask(ProjectSupportResourceHandler.Set_ClassPath__UI_); //$NON-NLS-1$ = "Set ClassPath:" // Tansfer the vector to an array IClasspathEntry[] newClassPathArray = new IClasspathEntry[newClassPathVector.size()]; for (int j = 0; j < newClassPathArray.length; j++) { newClassPathArray[j] = (IClasspathEntry) newClassPathVector.get(j); } // Only change the class path if there has been a modification if (needsToBeModified) { try { javaProject.setRawClasspath(newClassPathArray, localMonitor); } catch (Exception e) { WebPlugin.logError(e); } } } catch (ClassCastException ex) { WebPlugin.logError(ex); } catch (CoreException ex) { WebPlugin.logError(ex); } finally { localMonitor.done(); } } public static void updateContextRoot(IProject project, String contextRoot) { } /** * @param project * org.eclipse.core.resources.IProject */ /** * Returns a error message that states whether a context root is valid or not returns null if * context root is fine * * @return java.lang.String * @param contextRoot * java.lang.String */ public static String validateContextRoot(String contextRoot) { if (contextRoot == null) return null; String errorMessage = null; String name = contextRoot; if (name.equals("")) { //$NON-NLS-1$ // this was added because the error message shouldnt be shown initially. It should be // shown only if context root field is edited to errorMessage = ProjectSupportResourceHandler.Context_Root_cannot_be_empty_2; return errorMessage; } /******************************************************************************************* * // JZ - fix to defect 204264, "/" is valid in context root if (name.indexOf("//") != -1) { * //$NON-NLS-1$ errorMessage = "// are invalid characters in a resource name"; return * errorMessage; } ******************************************************************************************/ if (name.trim().equals(name)) { StringTokenizer stok = new StringTokenizer(name, "."); //$NON-NLS-1$ outer : while (stok.hasMoreTokens()) { String token = stok.nextToken(); int cp; for (int i = 0; i < token.length(); i += UTF16.getCharCount(cp)) { cp = UTF16.charAt(token, i); if (!(token.charAt(i) == '_') && !(token.charAt(i) == '-') && !(token.charAt(i) == '/') && Character.isLetterOrDigit(token.charAt(i)) == false) { if (Character.isWhitespace(token.charAt(i))) { // Removed because context roots can contain white space // errorMessage = // ResourceHandler.getString("_Context_root_cannot_conta_UI_");//$NON-NLS-1$ // = " Context root cannot contain whitespaces." } else { String invalidCharString = null; if (UTF16.getCharCount(cp)>1) { invalidCharString = UTF16.valueOf(cp); } else { invalidCharString = (new Character(token.charAt(i))).toString(); } Object[] invalidChar = new Object[]{invalidCharString}; errorMessage = ProjectSupportResourceHandler.getString(ProjectSupportResourceHandler.The_character_is_invalid_in_a_context_root, invalidChar); break outer; } } } } } // en/ end of if(name.trim else errorMessage = ProjectSupportResourceHandler.Names_cannot_begin_or_end_with_whitespace_5; return errorMessage; } /** * Return true if the string contains any of the characters in the array. */ private static boolean contains(String str, char[] chars) { for (int i = 0; i < chars.length; i++) { if (str.indexOf(chars[i]) != -1) return true; } return false; } public static String validateFolderName(String folderName) { if (folderName.length() == 0) return ProjectSupportResourceHandler.Folder_name_cannot_be_empty_2; if (contains(folderName, BAD_CHARS)) return ProjectSupportResourceHandler.getString(ProjectSupportResourceHandler.Folder_name_is_not_valid, new Object[]{folderName}); return null; } public static String validateWebContentName(String webContentName, IProject project, String javaSourceName) { String msg = validateFolderName(webContentName); if (msg != null) return msg; if (javaSourceName != null && webContentName.equals(javaSourceName)) return ProjectSupportResourceHandler.Folder_names_cannot_be_equal_4; // If given a java project, check to make sure current package fragment // root folders do not overlap with new web content name if (project != null) { IJavaProject javaProject = JemProjectUtilities.getJavaProject(project); if (javaProject != null) { try { IPackageFragmentRoot roots[] = javaProject.getPackageFragmentRoots(); for (int i = 0; i < roots.length; i++) { IPackageFragmentRoot root = roots[i]; if (!root.isArchive()) { IResource resource = root.getCorrespondingResource(); if (resource.getType() == IResource.FOLDER) { IPath path = resource.getFullPath(); String rootFolder = path.segment(1); if (webContentName.equals(rootFolder)) { if (root.getKind() == IPackageFragmentRoot.K_SOURCE) return ProjectSupportResourceHandler.Folder_name_cannot_be_the_same_as_Java_source_folder_5; return ProjectSupportResourceHandler.Folder_name_cannot_be_the_same_as_Java_class_folder_6; } } } } } catch (JavaModelException e) { return null; } } } return null; } /** * Update given web nature to the current version if necessary. * * @param webNature * The web Nature that should be examined. * @return True if successful, false if unnecessary. * @throws CoreException * The exception that occured during the version change operation. */ /* * static public boolean updateNatureToCurrentVersion(J2EEWebNatureRuntime webNature) throws * CoreException { * * boolean success = false; * * if (webNature.getVersion() != WEB.CURRENT_VERSION) { * webNature.setVersion(J2EESettings.CURRENT_VERSION); success = true; } * ((J2EEModuleWorkbenchURIConverterImpl) * webNature.getResourceSet().getURIConverter()).recomputeContainersIfNecessary(); * * return success; } */ /** * Move the old source folder to the new default folder. * * @param project * The Web Project we are working with. * @param oldSourceFolder * The old "Java Source" folder that will be moved. * @param javaSourceName * The new name of the "Java Source" folder, or null for default. * @return The location of the new folder, or null if no move was necessary. * @throws CoreException * The exception that occured during the move operation. */ static public IContainer updateJavaSourceName(IProject project, IContainer oldSourceFolder, String javaSourceName, IProgressMonitor progressMonitor) throws CoreException { IContainer newSourceFolder = null; if (oldSourceFolder != null) { IPath newPath; if (javaSourceName == null) newPath = new Path(DEFAULT_JAVA_SOURCE_NAME); else newPath = new Path(javaSourceName); // Make sure new path is different form old path if (!project.getFolder(newPath).getFullPath().equals(oldSourceFolder.getFullPath())) { oldSourceFolder.move(newPath, IResource.FORCE | IResource.KEEP_HISTORY, new SubProgressMonitor(progressMonitor, 1)); JemProjectUtilities.removeFromJavaClassPath(project, oldSourceFolder); newSourceFolder = project.getFolder(newPath); JemProjectUtilities.appendJavaClassPath(project, JavaCore.newSourceEntry(project.getFolder(newPath).getFullPath())); } } return newSourceFolder; } /** * Get the source folder that should be used for migration. * * @param project * The Web Project to examine. * @return The source folder to use in migration, or null if it should be skipped. */ static public IContainer getJavaSourceFolder(IProject project) { List sourceRoots = JemProjectUtilities.getSourceContainers(project); IContainer oldSourceFolder = null; if (sourceRoots != null) { if (sourceRoots.size() == 1) { IContainer sourceFolder = (IContainer) sourceRoots.get(0); if (sourceFolder instanceof IFolder) { oldSourceFolder = sourceFolder; } } } return oldSourceFolder; } public static IFolder getModuleServerRoot(IProject project) { // TODO need to implement module server root properly IPath compRootPath = ComponentCore.createComponent(project).getRootFolder().getUnderlyingFolder().getProjectRelativePath(); return project.getFolder(compRootPath); //return project.getFolder("WebContent"); } public static IVirtualFolder getWebLibFolder(IVirtualComponent webComponent) { IPath path = new Path(J2EEConstants.WEB_INF + "/" + "lib"); //$NON-NLS-1$//$NON-NLS-2$ IVirtualFolder libFolder = webComponent.getRootFolder().getFolder(path); return libFolder; } //TODO delete jsholl /** * @deprecated use getWebLibFolder(IVirtualComponent webComponent) * @param project * @return */ public static IContainer getWebLibFolder(IProject project) { return getWebLibFolder(ComponentCore.createComponent(project)).getUnderlyingFolder(); } // // static public boolean isImportedClassesJARFileInLibDir(IResource resource) { // if (resource == null || !resource.exists()) // return false; // return resource.getType() == resource.FILE && // resource.getName().endsWith(IWebNatureConstants.IMPORTED_CLASSES_SUFFIX) && isZip(resource); // } // // static public boolean isLibDirJARFile(IResource resource) { // if (resource == null || !resource.exists()) // return false; // return resource.getType() == resource.FILE && isZip(resource); // } // // static public boolean isZip(IResource resource) { // String path = resource.getLocation().toOSString(); // ZipFile zip = null; // // try { // zip = new ZipFile(path); // } catch (IOException notAZip) { // return false; // } finally { // if (zip != null) { // try { // zip.close(); // } catch (IOException ex) {} // } // } // return zip != null; // } }