| /******************************************************************************* |
| * Copyright (c) 2009, 2010 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 |
| * yyyymmdd bug Email and other contact information |
| * -------- -------- ----------------------------------------------------------- |
| * 20091021 291954 ericdp@ca.ibm.com - Eric D. Peters, JAX-RS: Implement JAX-RS Facet |
| * 20100304 304732 ericdp@ca.ibm.com - Eric D. Peters, NPE loading library extensions |
| * 20100407 308401 ericdp@ca.ibm.com - Eric D. Peters, JAX-RS facet wizard page - Shared-library option should be disabled |
| * 20100420 309846 ericdp@ca.ibm.com - Eric D. Peters, Remove dead code related to e.p. pluginProvidedJaxrsLibraries |
| *******************************************************************************/ |
| package org.eclipse.jst.ws.jaxrs.core.internal.jaxrslibraryconfig; |
| |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| 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.ws.jaxrs.core.internal.JAXRSCorePlugin; |
| import org.eclipse.jst.ws.jaxrs.core.internal.JAXRSLibraryClasspathContainer; |
| import org.eclipse.jst.ws.jaxrs.core.internal.Messages; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrsibraryregistry.ArchiveFile; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrsibraryregistry.JAXRSLibrary; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrsibraryregistry.JAXRSLibraryRegistry; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrsibraryregistry.JAXRSLibraryRegistryFactory; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrslibraryregistry.adapter.MaintainDefaultImplementationAdapter; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrslibraryregistry.impl.JAXRSLibraryRegistryPackageImpl; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrslibraryregistry.util.JAXRSLibraryRegistryResourceFactoryImpl; |
| import org.eclipse.jst.ws.jaxrs.core.internal.jaxrslibraryregistry.util.JAXRSLibraryRegistryResourceImpl; |
| import org.eclipse.jst.ws.jaxrs.core.jaxrslibraryconfiguration.internal.JAXRSLibraryConfigurationHelper; |
| import org.eclipse.jst.ws.jaxrs.core.jaxrslibraryregistry.internal.PluginProvidedJAXRSLibraryCreationHelper2; |
| |
| /** |
| * A singleton maintains lists of implementation libraries in registry. |
| * |
| * Each item in the lists contains a workingcopy of a JAX-RS library and |
| * decorates with usage information such selection and deployment. |
| * |
| * The lists are updated when there are changes in JAX-RS library registry. |
| * |
| */ |
| public class JAXRSLibraryRegistryUtil { |
| private static JAXRSLibraryRegistryUtil instance = null; |
| |
| private List<JAXRSLibraryInternalReference> implLibs = null; |
| |
| // The NS URI of the JAX-RS Library Registry's Ecore package. (Must match |
| // setting on package in Ecore model.) |
| private static final String JAXRS_LIBRARY_REGISTRY_NSURI = "http://www.eclipse.org/webtools/jaxrs/schema/jaxrslibraryregistry.xsd"; //$NON-NLS-1$ |
| |
| private static final String LIB_EXT_PT = "pluginProvidedJaxrsLibraries"; //$NON-NLS-1$ |
| |
| // The JAX-RS Library Registry EMF resource instance. |
| private static JAXRSLibraryRegistryResourceImpl JAXRSLibraryRegistryResource = null; |
| |
| // JAXRSLibraryRegistry singleton |
| private JAXRSLibraryRegistry JAXRSLibraryRegistry; |
| |
| /** |
| * Private constructor |
| */ |
| private JAXRSLibraryRegistryUtil() { |
| // nothing to do |
| } |
| |
| /** |
| * Return the singleton instance of JAXRSLibraryRegistryUtil. |
| * |
| * @return JAXRSLibraryRegistryUtil |
| */ |
| public synchronized static JAXRSLibraryRegistryUtil getInstance() { |
| if (instance == null) { |
| instance = new JAXRSLibraryRegistryUtil(); |
| instance.loadJAXRSLibraryRegistry(); |
| } |
| return instance; |
| } |
| |
| /** |
| * Convenience method to return the JAXRSLibraryRegistry instance. |
| * |
| * @return jaxrsLibReg JAXRSLibraryRegistry |
| */ |
| public JAXRSLibraryRegistry getJAXRSLibraryRegistry() { |
| return JAXRSLibraryRegistry; |
| } |
| |
| /** |
| * Get the default JAXRS implementation library instance. A null is returned |
| * when there is no libraries in the registry. |
| * |
| * @return JAXRSLibraryInternalReference |
| */ |
| public JAXRSLibraryInternalReference getDefaultJAXRSImplementationLibrary() { |
| JAXRSLibrary dftImplLib = getJAXRSLibraryRegistry() |
| .getDefaultImplementation(); |
| |
| return ((dftImplLib != null) ? getJAXRSLibraryReferencebyID(dftImplLib |
| .getID()) : null); |
| } |
| |
| /** |
| * Get the working copy of JAXRS implementation libraries. The list is |
| * updated when there are changes in registry. |
| * |
| * @return List |
| */ |
| List<JAXRSLibraryInternalReference> getJAXRSImplementationLibraries() { |
| if (implLibs == null) { |
| implLibs = wrapJAXRSLibraries(getJAXRSLibraryRegistry() |
| .getImplJAXRSLibraries()); |
| } else { |
| if (implLibs.size() != getJAXRSLibraryRegistry() |
| .getImplJAXRSLibraries().size() |
| || isAnyLibraryChanged(implLibs)) { |
| implLibs.clear(); |
| implLibs = wrapJAXRSLibraries(getJAXRSLibraryRegistry() |
| .getImplJAXRSLibraries()); |
| } |
| } |
| return implLibs; |
| } |
| |
| /** |
| * Get the JAXRSLibraryDecorator object from the provided ID. A null is |
| * returned no library matches the ID. |
| * |
| * @param id |
| * String |
| * @return JAXRSLibraryDecorator |
| */ |
| public JAXRSLibraryInternalReference getJAXRSLibraryReferencebyID( |
| final String id) { |
| Iterator<JAXRSLibraryInternalReference> it = getJAXRSImplementationLibraries() |
| .iterator(); |
| JAXRSLibraryInternalReference crtItem = null; |
| |
| // search implementation libraries |
| while (it.hasNext()) { |
| crtItem = it.next(); |
| if (id.equals(crtItem.getID())) { |
| return crtItem; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Add a JAXRS Library into collection for either JAXRS implementation |
| * libraries. The decision is based on if a JAXRS Library is an |
| * implementation. |
| * |
| * @param library |
| * JAXRSLibraryLibraryReference |
| */ |
| public void addJAXRSLibrary(final JAXRSLibraryInternalReference library) { |
| // Library is added only if it does not exist in registry |
| if (library != null |
| && getJAXRSLibraryRegistry().getJAXRSLibraryByID( |
| library.getID()) == null) { |
| // Add the library working copy into workspace registry. |
| JAXRSLibrary jaxrsLib = library.getLibrary(); |
| getJAXRSLibraryRegistry() |
| .addJAXRSLibrary(jaxrsLib.getWorkingCopy()); |
| |
| // Add library into the collection depends on its type. |
| List<JAXRSLibraryInternalReference> list = getJAXRSImplementationLibraries(); |
| list.add(library); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private List<JAXRSLibraryInternalReference> wrapJAXRSLibraries( |
| final EList libs) { |
| List<JAXRSLibraryInternalReference> list = new ArrayList<JAXRSLibraryInternalReference>(); |
| if (libs != null) { |
| JAXRSLibrary jaxrsLib; |
| JAXRSLibraryInternalReference jaxrsLibDctr; |
| |
| Iterator it = libs.iterator(); |
| while (it.hasNext()) { |
| jaxrsLib = (JAXRSLibrary) it.next(); |
| // Set selected , deployed , unshared initially |
| jaxrsLibDctr = new JAXRSLibraryInternalReference(jaxrsLib, |
| true, true, false); |
| list.add(jaxrsLibDctr); |
| } |
| } |
| return list; |
| } |
| |
| private boolean isAnyLibraryChanged( |
| final List<JAXRSLibraryInternalReference> list) { |
| Iterator<JAXRSLibraryInternalReference> it = list.iterator(); |
| JAXRSLibraryInternalReference wclib = null; // working copy library |
| JAXRSLibrary lib = null; |
| |
| while (it.hasNext()) { |
| wclib = it.next(); |
| lib = getJAXRSLibraryRegistry().getJAXRSLibraryByID(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; |
| } |
| |
| @SuppressWarnings("unchecked") |
| 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; |
| } |
| |
| @SuppressWarnings("unchecked") |
| 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 JAXRS Library |
| * |
| * @param lib |
| * @return IClasspathEntry[] |
| */ |
| @SuppressWarnings("unchecked") |
| public IClasspathEntry[] getClasspathEntries(JAXRSLibrary lib) { |
| // TODO: cache to optimize. probably belongs inside JAXRSLibrary model. |
| ArrayList<IClasspathEntry> res = new ArrayList<IClasspathEntry>(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 = 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 JAXRS 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( |
| JAXRSLibraryConfigurationHelper.JAXRS_LIBRARY_CP_CONTAINER_ID) |
| .append(newId); |
| IPath oldContainerPath = new Path( |
| JAXRSLibraryConfigurationHelper.JAXRS_LIBRARY_CP_CONTAINER_ID) |
| .append(oldId); |
| |
| JAXRSLibrary lib = JAXRSLibraryRegistryUtil.getInstance() |
| .getJAXRSLibraryRegistry().getJAXRSLibraryByID(newId); |
| List<IJavaProject> affectedProjects = new ArrayList<IJavaProject>(); |
| 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 = 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<IClasspathEntry> keptEntries = new ArrayList<IClasspathEntry>(); |
| // 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 |
| |
| JAXRSLibraryClasspathContainer container = new JAXRSLibraryClasspathContainer( |
| 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<IClasspathEntry> cpEntries, IProgressMonitor monitor) { |
| IClasspathEntry[] entries = cpEntries.toArray(new IClasspathEntry[0]); |
| try { |
| project.setRawClasspath(entries, monitor); |
| } catch (JavaModelException e) { |
| JAXRSCorePlugin.log(e, "Unable to set classpath for: " |
| + project.getProject().getName()); |
| } |
| } |
| |
| /** |
| * Return the URI for the specified JAXRS Library Registry |
| * |
| * @param registryVersion |
| * @return URI |
| * @throws MalformedURLException |
| */ |
| public static URI getRegistryURI(String registryVersion) |
| throws MalformedURLException { |
| URL jaxrsLibRegURL = new URL(Platform.getInstanceLocation().getURL(), |
| registryVersion); |
| return URI.createURI(jaxrsLibRegURL.toString()); |
| } |
| |
| /** |
| * Loads the JAXRSLibraryRegistry EMF object from plugin-specfic workspace |
| * settings location. |
| */ |
| private void loadJAXRSLibraryRegistry() { |
| try { |
| |
| EPackage.Registry.INSTANCE.put(JAXRS_LIBRARY_REGISTRY_NSURI, |
| JAXRSLibraryRegistryPackageImpl.init()); |
| URI jaxrsLibRegURI = getRegistryURI(".metadata/.plugins/org.eclipse.jst.ws.jaxrs.core/JAXRSLibraryRegistry.xml"); |
| |
| JAXRSLibraryRegistryResourceFactoryImpl resourceFactory = new JAXRSLibraryRegistryResourceFactoryImpl(); |
| JAXRSLibraryRegistryResource = (JAXRSLibraryRegistryResourceImpl) resourceFactory |
| .createResource(jaxrsLibRegURI); |
| try { |
| Map<String, Boolean> options = new HashMap<String, Boolean>(); |
| // disable notifications during load to avoid changing stored |
| // default implementation |
| options.put(XMLResource.OPTION_DISABLE_NOTIFY, Boolean.TRUE); |
| JAXRSLibraryRegistryResource.load(options); |
| JAXRSLibraryRegistry = (JAXRSLibraryRegistry) JAXRSLibraryRegistryResource |
| .getContents().get(0); |
| |
| loadJAXRSLibraryExtensions(); |
| |
| } catch (IOException ioe) { |
| // Create a new Registry instance |
| JAXRSLibraryRegistry = JAXRSLibraryRegistryFactory.eINSTANCE |
| .createJAXRSLibraryRegistry(); |
| JAXRSLibraryRegistryResource = (JAXRSLibraryRegistryResourceImpl) resourceFactory |
| .createResource(jaxrsLibRegURI); |
| JAXRSLibraryRegistryResource.getContents().add( |
| JAXRSLibraryRegistry); |
| loadJAXRSLibraryExtensions(); |
| saveJAXRSLibraryRegistry(); |
| } |
| // add adapter to maintain default implementation |
| if (JAXRSLibraryRegistry != null) { |
| // check that a default impl is set. if not pick first one if |
| // available. |
| JAXRSLibrary defLib = JAXRSLibraryRegistry |
| .getDefaultImplementation(); |
| if (defLib == null |
| && JAXRSLibraryRegistry.getImplJAXRSLibraries().size() > 0) { |
| JAXRSLibraryRegistry |
| .setDefaultImplementation((JAXRSLibrary) JAXRSLibraryRegistry |
| .getImplJAXRSLibraries().get(0)); |
| saveJAXRSLibraryRegistry(); |
| } |
| JAXRSLibraryRegistry.eAdapters().add( |
| MaintainDefaultImplementationAdapter.getInstance()); |
| |
| } |
| } catch (MalformedURLException mue) { |
| JAXRSCorePlugin.log(IStatus.ERROR, |
| Messages.JAXRSLibraryRegistry_ErrorCreatingURL, mue); |
| } |
| } |
| |
| // /////////////////////////////// Load and Save JAXRS Library Registry |
| // //////////////////////////////////////////////// |
| |
| /** |
| * Creates library registry items from extension points. |
| */ |
| private void loadJAXRSLibraryExtensions() { |
| try { |
| IExtensionPoint point = Platform.getExtensionRegistry() |
| .getExtensionPoint(JAXRSCorePlugin.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++) { |
| PluginProvidedJAXRSLibraryCreationHelper2 newLibCreator = new PluginProvidedJAXRSLibraryCreationHelper2( |
| ext.getConfigurationElements()[j]); |
| JAXRSLibrary newLib = newLibCreator.create(); |
| |
| if (newLib != null) |
| JAXRSLibraryRegistry.addJAXRSLibrary(newLib); |
| } |
| } |
| } catch (InvalidRegistryObjectException e) { |
| JAXRSCorePlugin.log(IStatus.ERROR, |
| Messages.JAXRSLibraryRegistry_ErrorLoadingFromExtPt, e); |
| } |
| } |
| |
| /** |
| * Saves the JAXRSLibraryRegistry EMF object from plugin-specfic workspace |
| * settings location. (Called from stop(BundleContext).) |
| * |
| * @return true if save is successful |
| */ |
| public boolean saveJAXRSLibraryRegistry() { |
| boolean saved = false; |
| if (JAXRSLibraryRegistryResource != null) { |
| try { |
| JAXRSLibraryRegistryResource.save(Collections.EMPTY_MAP); |
| saved = true; |
| } catch (IOException ioe) { |
| JAXRSCorePlugin.log(IStatus.ERROR, |
| Messages.JAXRSLibraryRegistry_ErrorSaving, ioe); |
| } |
| } else { |
| JAXRSCorePlugin.log(IStatus.ERROR, |
| Messages.JAXRSLibraryRegistry_ErrorSaving); |
| } |
| return saved; |
| } |
| |
| } |