/******************************************************************************* * Copyright (c) 2006 Oracle Corporation. * 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: Oracle *******************************************************************************/ package org.eclipse.jst.jsf.core.internal.jsflibraryconfig; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; import org.eclipse.jst.jsf.core.internal.JSFLibraryClasspathContainer; import org.eclipse.jst.jsf.core.internal.Messages; import org.eclipse.jst.jsf.core.internal.RegistryUpgradeCommitHandler; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.ArchiveFile; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.JSFLibrary; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.JSFLibraryRegistry; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.JSFLibraryRegistryFactory; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.adapter.MaintainDefaultImplementationAdapter; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.impl.JSFLibraryRegistryPackageImpl; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.util.JSFLibraryRegistryResourceFactoryImpl; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.util.JSFLibraryRegistryResourceImpl; import org.eclipse.jst.jsf.core.internal.jsflibraryregistry.util.JSFLibraryRegistryUpgradeUtil; import org.eclipse.jst.jsf.core.jsflibraryconfiguration.JSFLibraryConfigurationHelper; import org.eclipse.jst.jsf.core.jsflibraryregistry.PluginProvidedJSFLibraryCreationHelper; import org.eclipse.jst.jsf.core.jsflibraryregistry.internal.PluginProvidedJSFLibraryCreationHelper2; /** * A singleton maintains lists of implementation and component libraries * in registry. * * Each item in the lists contains a workingcopy of a JSF library and * decorates with usage information such selection and deployment. * * The lists are updated when there are changes in JSF library registry. * * @author Justin Chen, etc. - Oracle * @deprecated */ public class JSFLibraryRegistryUtil { private static JSFLibraryRegistryUtil instance = null; private List implLibs = null; private List compLibs = null; // The NS URI of the JSF Library Registry's Ecore package. (Must match // setting on package in Ecore model.) private static final String JSF_LIBRARY_REGISTRY_NSURI = "http://www.eclipse.org/webtools/jsf/schema/jsflibraryregistry.xsd"; //$NON-NLS-1$ private static final String LIB_EXT_PT = "pluginProvidedJsfLibraries"; //$NON-NLS-1$ //deprecated ext-pt private static final String OLD_LIB_EXT_PT = "jsfLibraries"; //$NON-NLS-1$ // The JSF Library Registry EMF resource instance. private static JSFLibraryRegistryResourceImpl jsfLibraryRegistryResource = null; //JSFLibraryRegistry singleton private JSFLibraryRegistry jsfLibraryRegistry; /** * Private constructor */ private JSFLibraryRegistryUtil() { //nothing to do } /** * Return the singleton instance of JSFLibraryRegistryUtil. * * @return JSFLibraryRegistryUtil */ public synchronized static JSFLibraryRegistryUtil getInstance() { if ( instance == null ) { instance = new JSFLibraryRegistryUtil(); instance.loadJSFLibraryRegistry(); } return instance; } /** * Convenience method to return the JSFLibraryRegistry instance. * * @return jsfLibReg JSFLibraryRegistry */ public JSFLibraryRegistry getJSFLibraryRegistry() { return jsfLibraryRegistry; } /** * Get the default JSF implementation library instance. * A null is returned when there is no libraries in the registry. * * @return JSFLibraryInternalReference */ public JSFLibraryInternalReference getDefaultJSFImplementationLibrary() { JSFLibrary dftImplLib = getJSFLibraryRegistry().getDefaultImplementation(); return ((dftImplLib != null) ? getJSFLibraryReferencebyID(dftImplLib.getID()) : null); } /** * Get the working copy of JSF implementation libraries. * The list is updated when there are changes in registry. * * @return List */ List getJSFImplementationLibraries() { if (implLibs == null) { implLibs = wrapJSFLibraries(getJSFLibraryRegistry().getImplJSFLibraries()); } else { if (implLibs.size() != getJSFLibraryRegistry().getImplJSFLibraries().size() || isAnyLibraryChanged(implLibs)) { implLibs.clear(); implLibs = wrapJSFLibraries(getJSFLibraryRegistry().getImplJSFLibraries()); } } return implLibs; } /** * Get the working copy of JSF component libraries. * The list is updated when there are changes in registry. * * @return List */ List getJSFComponentLibraries() { if (compLibs == null) { compLibs = wrapJSFLibraries(getJSFLibraryRegistry().getNonImplJSFLibraries()); } else { if (compLibs.size() != getJSFLibraryRegistry().getNonImplJSFLibraries().size() || isAnyLibraryChanged(compLibs)) { compLibs.clear(); compLibs = wrapJSFLibraries(getJSFLibraryRegistry().getNonImplJSFLibraries()); } } return compLibs; } /** * Get the JSFLibraryDecorator object from the provided ID. * A null is returned no library matches the ID. * * @param id String * @return JSFLibraryDecorator */ public JSFLibraryInternalReference getJSFLibraryReferencebyID(final String id) { Iterator it = getJSFImplementationLibraries().iterator(); JSFLibraryInternalReference crtItem = null; // search implementation libraries while(it.hasNext()) { crtItem = (JSFLibraryInternalReference)it.next(); if (id.equals(crtItem.getID())) { return crtItem; } } // search component libraries it = getJSFComponentLibraries().iterator(); while(it.hasNext()) { crtItem = (JSFLibraryInternalReference)it.next(); if (id.equals(crtItem.getID())) { return crtItem; } } return null; } /** * Add a JSF Library into collection for either * JSF implementation libraries or component libraries. * The decision is based on if a JSF library is an implementation. * * @param library JSFLibraryLibraryReference */ public void addJSFLibrary(final JSFLibraryInternalReference library) { // Library is added only if it does not exist in registry if (library != null && getJSFLibraryRegistry().getJSFLibraryByID(library.getID()) == null) { // Add the library working copy into workspace registry. JSFLibrary jsfLib = library.getLibrary(); getJSFLibraryRegistry().addJSFLibrary(jsfLib.getWorkingCopy()); // Add library into the collection depends on its type. List list = (library.isImplementation() ? getJSFImplementationLibraries() : getJSFComponentLibraries()); list.add(library); } } private List wrapJSFLibraries(final EList libs) { List list = new ArrayList(); if (libs != null) { JSFLibrary jsfLib; JSFLibraryInternalReference jsfLibDctr; Iterator it = libs.iterator(); while (it.hasNext()) { jsfLib = (JSFLibrary) it.next(); // Set unselected and undeployed initially. jsfLibDctr = new JSFLibraryInternalReference(jsfLib, //.getWorkingCopy(), false, false); list.add(jsfLibDctr); } } return list; } private boolean isAnyLibraryChanged(final List list) { Iterator it = list.iterator(); JSFLibraryInternalReference wclib = null; // working copy library JSFLibrary lib = null; while(it.hasNext()) { wclib = (JSFLibraryInternalReference)it.next(); lib = getJSFLibraryRegistry().getJSFLibraryByID(wclib.getID()); if (lib == null) { // removed. Hence, changed. return true; } if (wclib.getArchiveFiles().size() != lib.getArchiveFiles().size()) { // Archives changed.. return true; } if (isAnyArchiveFileChanged(wclib.getArchiveFiles(), lib.getArchiveFiles())) { // Check archive file changes. I.e., name and location return true; } } return false; } private boolean isAnyArchiveFileChanged(final EList source, EList target) { ArchiveFile arSrc = null; Iterator it = source.iterator(); while (it.hasNext()) { arSrc = (ArchiveFile) it.next(); if (!findMatchedArchive(arSrc, target)) { return true; } } return false; } private boolean findMatchedArchive(ArchiveFile source, EList list) { ArchiveFile target = null; Iterator it = list.iterator(); while (it.hasNext()) { target = (ArchiveFile) it.next(); if (target.equals(source)) { return true; } } return false; } /** * Get the classpath entries for a JSF Library * @param lib * @return IClasspathEntry[] */ public IClasspathEntry[] getClasspathEntries(JSFLibrary lib){ //TODO: cache to optimize. probably belongs inside JSFLibrary model. ArrayList res= new ArrayList(lib.getArchiveFiles().size()); for (Iterator it=lib.getArchiveFiles().iterator();it.hasNext();) { ArchiveFile jar= (ArchiveFile)it.next(); if (jar != null && jar.exists()) { IClasspathEntry entry = getClasspathEntry(jar); if (entry != null) res.add(entry); } } IClasspathEntry[] entries= (IClasspathEntry[]) res.toArray(new IClasspathEntry[res.size()]); return entries; } /** * Create IClasspathEntry for ArchiveFile * @param jar * @return IClasspathEntry */ public IClasspathEntry getClasspathEntry(ArchiveFile jar){ IClasspathEntry entry = null; if (jar !=null && jar.exists()){ entry = JavaCore.newLibraryEntry(new Path(jar.getResolvedSourceLocation()), null, null);//, nu, sourceAttachRoot, accessRules, extraAttributes, false/*not exported*/); } return entry; } /** * Binds JSF Libraries to classpath containers when the library changes. * * This method will deal with library/cp container renames by removing the old classpath container and then adding. * * @param oldId * @param newId * @param monitor * @throws JavaModelException */ public static void rebindClasspathContainerEntries(String oldId, String newId, IProgressMonitor monitor) throws JavaModelException { IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); IJavaProject[] projects= JavaCore.create(root).getJavaProjects(); IPath containerPath= new Path(JSFLibraryConfigurationHelper.JSF_LIBRARY_CP_CONTAINER_ID).append(newId); IPath oldContainerPath = new Path(JSFLibraryConfigurationHelper.JSF_LIBRARY_CP_CONTAINER_ID).append(oldId); JSFLibrary lib = JSFLibraryRegistryUtil.getInstance().getJSFLibraryRegistry().getJSFLibraryByID(newId); List affectedProjects= new ArrayList(); boolean removeAndAddBecauseOfRename = (!oldId.equals(newId)); // find all projects using the old container name... for (int i= 0; i < projects.length; i++) { IJavaProject project= projects[i]; IClasspathEntry[] entries= project.getRawClasspath(); for (int k= 0; k < entries.length; k++) { IClasspathEntry curr= entries[k]; if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { if (oldContainerPath.equals(curr.getPath())) { affectedProjects.add(project); break; } } } } if (!affectedProjects.isEmpty()) { IJavaProject[] affected= (IJavaProject[]) affectedProjects.toArray(new IJavaProject[affectedProjects.size()]); IClasspathContainer[] containers= new IClasspathContainer[affected.length]; removeAndAddBecauseOfRename = (!oldId.equals(newId)); if (removeAndAddBecauseOfRename){//not very pretty... remove and add new container IClasspathEntry newEntry = JavaCore.newContainerEntry(containerPath); for (int i= 0; i < affected.length; i++) { IJavaProject project= affected[i]; IClasspathEntry[] entries= project.getRawClasspath(); List keptEntries = new ArrayList(); //keep all entries except the old one for (int k= 0; k < entries.length; k++) { IClasspathEntry curr= entries[k]; if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER){ if( ! oldContainerPath.equals(curr.getPath())) keptEntries.add(curr); } else { keptEntries.add(curr); } } // add new container entry keptEntries.add(newEntry); setRawClasspath(project, keptEntries, monitor); } } else {//rebind JSFLibraryClasspathContainer container= new JSFLibraryClasspathContainer(lib); containers[0] = container; JavaCore.setClasspathContainer(containerPath, affected, containers, monitor); } } else { if (monitor != null) { monitor.done(); } } } /** * Sets the raw classpath on a project and logs an error if it when a JavaModelException occurs * @param project * @param cpEntries * @param monitor */ public static void setRawClasspath(IJavaProject project, List cpEntries, IProgressMonitor monitor) { IClasspathEntry[] entries = (IClasspathEntry[])cpEntries.toArray(new IClasspathEntry[0]); try { project.setRawClasspath(entries, monitor); } catch (JavaModelException e) { JSFCorePlugin.log(e, "Unable to set classpath for: "+project.getProject().getName()); //$NON-NLS-1$ } } /** * Loads the JSFLibraryRegistry EMF object from plugin-specfic workspace * settings location. */ private void loadJSFLibraryRegistry() { try { EPackage.Registry.INSTANCE.put(JSF_LIBRARY_REGISTRY_NSURI, JSFLibraryRegistryPackageImpl.init()); URI jsfLibRegURI = JSFLibraryRegistryUpgradeUtil.getRegistryURI(JSFLibraryRegistryUpgradeUtil.JSF_LIBRARY_REGISTRY_LATESTVERSION_URL); JSFLibraryRegistryUpgradeUtil.getInstance().upgradeRegistryIfNecessary(JSFLibraryRegistryUpgradeUtil.LATESTVERSION); JSFLibraryRegistryResourceFactoryImpl resourceFactory = new JSFLibraryRegistryResourceFactoryImpl(); jsfLibraryRegistryResource = (JSFLibraryRegistryResourceImpl)resourceFactory.createResource(jsfLibRegURI); try { Map options = new HashMap(); //disable notifications during load to avoid changing stored default implementation options.put(XMLResource.OPTION_DISABLE_NOTIFY, Boolean.TRUE); jsfLibraryRegistryResource.load(options); jsfLibraryRegistry = (JSFLibraryRegistry)jsfLibraryRegistryResource.getContents().get(0); loadJSFLibraryExtensions(); loadDeprecatedJSFLibraryExtensions();//to be removed } catch(IOException ioe) { //Create a new Registry instance jsfLibraryRegistry = JSFLibraryRegistryFactory.eINSTANCE.createJSFLibraryRegistry(); jsfLibraryRegistryResource = (JSFLibraryRegistryResourceImpl)resourceFactory.createResource(jsfLibRegURI); jsfLibraryRegistryResource.getContents().add(jsfLibraryRegistry); loadJSFLibraryExtensions(); loadDeprecatedJSFLibraryExtensions();//to be removed saveJSFLibraryRegistry(); } //add adapter to maintain default implementation if (jsfLibraryRegistry != null) { //check that a default impl is set. if not pick first one if available. JSFLibrary defLib = jsfLibraryRegistry.getDefaultImplementation(); if (defLib == null && jsfLibraryRegistry.getImplJSFLibraries().size() > 0){ jsfLibraryRegistry.setDefaultImplementation((JSFLibrary)jsfLibraryRegistry.getImplJSFLibraries().get(0)); saveJSFLibraryRegistry(); } jsfLibraryRegistry.eAdapters().add(MaintainDefaultImplementationAdapter.getInstance()); //commit RegistryUpgradeCommitHandler.commitMigrationIfNecessary(); } } catch(MalformedURLException mue) { JSFCorePlugin.log(IStatus.ERROR, Messages.JSFLibraryRegistry_ErrorCreatingURL, mue); } } ///////////////////////////////// Load and Save JSF Library Registry //////////////////////////////////////////////// /** * Creates library registry items from extension points. */ private void loadJSFLibraryExtensions() { try { IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(JSFCorePlugin.PLUGIN_ID, LIB_EXT_PT); IExtension[] extensions = point.getExtensions(); for (int i=0;i < extensions.length;i++){ IExtension ext = extensions[i]; for (int j=0;j < ext.getConfigurationElements().length;j++){ PluginProvidedJSFLibraryCreationHelper2 newLibCreator = new PluginProvidedJSFLibraryCreationHelper2(ext.getConfigurationElements()[j]); JSFLibrary newLib = newLibCreator.create(); /** * Additional check on if a plug-in contributes jsflibraries is an expanded folder. * Fix related to bug 144954. * * It would be ideal to check if a plug-in is distributed as a JAR * before a JSFLibrary is created. * * This is a temporary solution since JARs in a JAR case is not * supported in this release. Bug 14496. */ if (newLib != null) //&& isJSFLibinExpandedFolder(newLib)) jsfLibraryRegistry.addJSFLibrary(newLib); } } } catch (InvalidRegistryObjectException e) { JSFCorePlugin.log(IStatus.ERROR, Messages.JSFLibraryRegistry_ErrorLoadingFromExtPt, e); } } /** * Creates deprecated library registry items from extension points. * TO BE REMOVED */ private void loadDeprecatedJSFLibraryExtensions() { try { IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(JSFCorePlugin.PLUGIN_ID, OLD_LIB_EXT_PT); IExtension[] extensions = point.getExtensions(); for (int i=0;i < extensions.length;i++){ IExtension ext = extensions[i]; for (int j=0;j < ext.getConfigurationElements().length;j++){ PluginProvidedJSFLibraryCreationHelper newLibCreator = new PluginProvidedJSFLibraryCreationHelper(ext.getConfigurationElements()[j]); JSFLibrary newLib = newLibCreator.create(); /** * Additional check on if a plug-in contributes jsflibraries is an expanded folder. * Fix related to bug 144954. * * It would be ideal to check if a plug-in is distributed as a JAR * before a JSFLibrary is created. * * This is a temporary solution since JARs in a JAR case is not * supported in this release. Bug 14496. */ if (newLib != null ) //&& isJSFLibinExpandedFolder(newLib)) jsfLibraryRegistry.addJSFLibrary(newLib); } } } catch (InvalidRegistryObjectException e) { JSFCorePlugin.log(IStatus.ERROR, Messages.JSFLibraryRegistry_ErrorLoadingFromExtPt, e); } } /** * Saves the JSFLibraryRegistry EMF object from plugin-specfic workspace * settings location. (Called from stop(BundleContext).) * @return true if save is successful */ public boolean saveJSFLibraryRegistry() { boolean saved = false; if (jsfLibraryRegistryResource != null) { try { jsfLibraryRegistryResource.save(Collections.EMPTY_MAP); saved = true; } catch(IOException ioe) { JSFCorePlugin.log(IStatus.ERROR, Messages.JSFLibraryRegistry_ErrorSaving, ioe); } } else { JSFCorePlugin.log(IStatus.ERROR, Messages.JSFLibraryRegistry_ErrorSaving); } return saved; } }