diff options
Diffstat (limited to 'plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java')
-rw-r--r-- | plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java | 1026 |
1 files changed, 0 insertions, 1026 deletions
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java deleted file mode 100644 index 49e1959e0..000000000 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java +++ /dev/null @@ -1,1026 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2006 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.jem.internal.beaninfo.adapters; -/* - - - */ - -import java.io.*; -import java.text.MessageFormat; -import java.util.*; -import java.util.logging.Level; - -import javax.xml.parsers.*; -import javax.xml.transform.*; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; -import org.eclipse.jdt.core.*; -import org.osgi.framework.Bundle; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.InputSource; - -import org.eclipse.jem.internal.beaninfo.core.*; -import org.eclipse.jem.internal.java.beaninfo.IIntrospectionAdapter; -import org.eclipse.jem.internal.java.init.JavaInit; -import org.eclipse.jem.internal.plugin.JavaEMFNature; -import org.eclipse.jem.internal.proxy.core.*; -import org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo.ContainerPaths; -import org.eclipse.jem.java.adapters.JavaXMIFactory; -import org.eclipse.jem.util.emf.workbench.ProjectResourceSet; -import org.eclipse.jem.util.emf.workbench.ResourceHandler; - - -/** - * The beaninfo nature. It is created for a project and holds the - * necessary info for beaninfo to be performed on a project. - */ - -public class BeaninfoNature implements IProjectNature { - - public static final String NATURE_ID = BeaninfoPlugin.PI_BEANINFO_PLUGINID + ".BeanInfoNature"; //$NON-NLS-1$ - public static final String P_BEANINFO_SEARCH_PATH = ".beaninfoConfig"; //$NON-NLS-1$ - - public static final QualifiedName CONFIG_INFO_SESSION_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "CONFIG_INFO"); //$NON-NLS-1$ - public static final QualifiedName BEANINFO_CONTRIBUTORS_SESSION_KEY = new QualifiedName(BeaninfoPlugin.PI_BEANINFO_PLUGINID, "BEANINFO_CONTRIBUTORS"); //$NON-NLS-1$ - - private ProxyFactoryRegistry.IRegistryListener registryListener = new ProxyFactoryRegistry.IRegistryListener() { - /** - * @see org.eclipse.jem.internal.proxy.core.ProxyFactoryRegistry.IRegistryListener#registryTerminated(ProxyFactoryRegistry) - */ - public void registryTerminated(ProxyFactoryRegistry registry) { - prematureRegistryTerminate(); - markAllStale(); - }; - }; - - /** - * Get the runtime nature for the project, create it if necessary. - */ - public static BeaninfoNature getRuntime(IProject project) throws CoreException { - JavaEMFNature.createRuntime(project); // Must force JAVAEMFNature creation first before we try to get ours. There is a chicken/egg problem if we let our nature try to get JavaEMFNature during setProject. - if (project.hasNature(NATURE_ID)) - return (BeaninfoNature) project.getNature(NATURE_ID); - else - return createRuntime(project); - } - - /** - * Return whether this project has a BeanInfo runtime turned on. - * - * @param project - * @return <code>true</code> if it has the a BeanInfo runtime. - * @throws CoreException - * - * @since 1.0.0 - */ - public static boolean hasRuntime(IProject project) throws CoreException { - return project.hasNature(NATURE_ID); - } - - /** - * Test if this is a valid project for a Beaninfo Nature. It must be - * a JavaProject. - */ - public static boolean isValidProject(IProject project) { - try { - return project.hasNature(JavaCore.NATURE_ID); - } catch (CoreException e) { - return false; - } - } - - /** - * Create the runtime. - */ - private static BeaninfoNature createRuntime(IProject project) throws CoreException { - if (!isValidProject(project)) - throw new CoreException( - new Status( - IStatus.ERROR, - BeaninfoPlugin.PI_BEANINFO_PLUGINID, - 0, - MessageFormat.format( - BeanInfoAdapterMessages.INTROSPECT_FAILED_EXC_, - new Object[] { project.getName(), BeanInfoAdapterMessages.BeaninfoNature_InvalidProject}), - null)); - - addNatureToProject(project, NATURE_ID); - return (BeaninfoNature) project.getNature(NATURE_ID); - } - - private static void addNatureToProject(IProject proj, String natureId) throws CoreException { - IProjectDescription description = proj.getDescription(); - String[] prevNatures = description.getNatureIds(); - String[] newNatures = new String[prevNatures.length + 1]; - System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); - newNatures[prevNatures.length] = natureId; - description.setNatureIds(newNatures); - proj.setDescription(description, null); - } - - private IProject fProject; - protected ProxyFactoryRegistry fRegistry; - protected ResourceSet javaRSet; - protected BeaninfoModelSynchronizer fSynchronizer; - protected static BeaninfoJavaReflectionKeyExtension fReflectionKeyExtension; - - /** - * Configures the project with this nature. - * This is called by <code>IProject.getNature</code> and should not - * be called directly by clients. - * The nature extension id is added to the list of natures on the project by - * <code>IProject.getNature</code>, and need not be added here. - * - * @exception CoreException if this method fails. - */ - public void configure() throws CoreException { - } - - /** - * Removes this nature from the project, performing any required deconfiguration. - * This is called by <code>IProject.removeNature</code> and should not - * be called directly by clients. - * The nature id is removed from the list of natures on the project by - * <code>IProject.removeNature</code>, and need not be removed here. - * - * @exception CoreException if this method fails. - */ - public void deconfigure() throws CoreException { - removeSharedProperty(P_BEANINFO_SEARCH_PATH, null); - cleanup(true, true); - } - - /** - * Shutdown the nature. Called by BeanInfoPlugin to tell the nature that the plugin is being shutdown. - * It needs to cleanup. - * TODO <package-protected> because only BeanInfoPlugin should call it. (public for now but when we make - * BeanInfoNature an API it will be moved into the same package as BeanInfoPlugin). - * - * @since 1.0.0 - */ - public void shutdown() { - cleanup(true, false); - } - - - /** - * Return a new ResourceSet that is linked correctly to this Beaninfo Nature. - * <p> - * This links up a ResourceSet so that it will work correctly with this nature. - * It makes sure that going through the ResourceSet that any "java:/..." - * classes can be found and it makes sure that any new classes are placed into the - * nature's resource set and not resource set doing the calling. - * <p> - * This should be used any time a resource set is needed that is not the - * project wide resource set associated with beaninfos, but will reference - * Java Model classes or instantiate. - * <p> - * An additional change is made too. The ResourceFactoryRegistry's extensionToResourceFactory map is modified - * to have an "java"->XMIResourceFactory entry added to it if EMF Examples is loaded. EMF Examples add - * the "java" extension and sets it to their own special JavaResourceFactory. - * If EMF Examples is not loaded, then it falls back to the default "*" mapping, which is to XMIResourceFactory. - * This normally causes problems for many - * customers. If users of this resource set really want the EMF examples entry instead, after they retrieve the - * new resource set they can do this: - * <p> - * <pre><code> - * rset = beaninfoNature.newResourceSet(); - * rset.getResourceFactoryRegistry().getExtensionToFactoryMap().remove("java"); - * </code></pre> - * - * @return a ResourceSet that is specially connected to the JEM java model. - * - * @since 1.0.0 - */ - public ProjectResourceSet newResourceSet() { - SpecialResourceSet rset = new SpecialResourceSet(); - rset.add(new ResourceHandler() { - public EObject getEObjectFailed(ResourceSet originatingResourceSet, URI uri, boolean loadOnDemand) { - return null; // We don't have any special things we can do in this case. - } - - public Resource getResource(ResourceSet originatingResourceSet, URI uri) { - // Always try to get it out of the nature's resource set because it may of been loaded there either as - // the "java:..." type or it could of been an override extra file (such as an override EMF package, for - // example jcf has a side package containing the definition of the new attribute type. That file - // will also be loaded into this resourceset. So to find it we need to go in here and try. - // - // However, if not found we won't go and try to load the resource. That could load in the wrong place. - // Kludge: Because of a bug (feature :-)) in XMLHandler.getPackageFromURI(), it doesn't use getResource(...,true) and it tries instead - // to use uri inputstream to load the package when not found. This bypasses our special create resource and so - // packages are not automatically created. So we need to do load on demand here instead if it is a java protocol. - // EMF will not be fixing this. It is working as designed. - return getResourceSet().getResource(uri, JavaXMIFactory.SCHEME.equals(uri.scheme())); - } - - public Resource createResource(ResourceSet originatingResourceSet, URI uri) { - // This is the one. It has got here because it couldn't find a resource already loaded. - // If it is a "java:/..." protocol resource, then we want to make sure it is loaded at the BeaninfoNature context - // instead of the lower one. - if (JavaXMIFactory.SCHEME.equals(uri.scheme())) - return getResourceSet().getResource(uri, true); - else - return null; - } - }); - // [71473] Restore "*.java" to be an XMIResource. If EMF Examples are loaded they overload this and load their special resource for "*.java" which we don't want. - // If some user really wants that, they grab the resource resource set and remove our override. - if (Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("java")) { //$NON-NLS-1$ - // Need to add an override to go to XMI instead. - rset.getResourceFactoryRegistry().getExtensionToFactoryMap().put("java", new XMIResourceFactoryImpl()); //$NON-NLS-1$ - } - return rset; - } - /** - * Clean up, this means either the project is being closed, deleted, or it means that - * the nature is being removed from the project. Either way that means to - * terminate the VM and remove what we added to the context if the flag says clear it. - * <p> - * This should be called ONLY when this instance of the nature is no longer needed. It - * will be recreated for any new uses. That is because we will be removing ourselves - * from the list of active natures in the BeanInfoPlugin. - * <p> - * <b>Note:</b> This will be called from the BeanInfoCacheController. It knows when the project is - * being closed or deleted. - * - * @param clearResults clear the results such that any JEM model objects have no BeanInfo - * adapters attached to them. This allows BeanInfo to be GC'd without being hung onto. - * - * @param deregister Deregister from the BeanInfoPlugin. Normally this will always be true, but it - * will be called with false when BeanInfoPlugin is calling back to shutdown. - */ - public synchronized void cleanup(boolean clearResults, boolean deregister) { - if (deregister) - BeaninfoPlugin.getPlugin().removeBeanInfoNature(this); - fSynchronizer.stopSynchronizer(clearResults); - Init.cleanup(javaRSet, clearResults); - if (fRegistry != null) - fRegistry.terminateRegistry(true); - - projectCleaned(); - javaRSet = null; - fRegistry = null; - fProject = null; - fSynchronizer = null; - } - - /** - * Returns the project to which this project nature applies. - * - * @return the project handle - */ - public IProject getProject() { - return fProject; - } - - /** - * Sets the project to which this nature applies. - * Used when instantiating this project nature runtime. - * This is called by <code>IProject.addNature</code> - * and should not be called directly by clients. - * - * @param project the project to which this nature applies - */ - public void setProject(IProject project) { -// BeanInfoCacheController.INSTANCE.getClass(); // Instantiates the controller if not already started. - fProject = project; - BeaninfoPlugin.getPlugin().addBeanInfoNature(this); - - try { - // The nature has been started for this project, need to setup the introspection process now. - JavaEMFNature javaNature = JavaEMFNature.createRuntime(fProject); - JavaInit.init(); - if (fReflectionKeyExtension == null) { - // Register the reflection key extension. - fReflectionKeyExtension = new BeaninfoJavaReflectionKeyExtension(); - JavaXMIFactory.INSTANCE.registerReflectionKeyExtension(fReflectionKeyExtension); - } - - javaRSet = javaNature.getResourceSet(); - Init.initialize(javaRSet, new IBeaninfoSupplier() { - public ProxyFactoryRegistry getRegistry() { - return BeaninfoNature.this.getRegistry(); - } - - public boolean isRegistryCreated() { - return BeaninfoNature.this.isRegistryCreated(); - } - - public void closeRegistry() { - BeaninfoNature.this.closeRegistry(); - } - - public IProject getProject() { - return BeaninfoNature.this.getProject(); - } - - public ProjectResourceSet getNewResourceSet() { - return BeaninfoNature.this.newResourceSet(); - } - - public ResourceSet getProjectResourceSet() { - return getResourceSet(); - } - }); - fSynchronizer = - new BeaninfoModelSynchronizer( - (BeaninfoAdapterFactory) EcoreUtil.getAdapterFactory(javaRSet.getAdapterFactories(), IIntrospectionAdapter.ADAPTER_KEY), - JavaCore.create(javaNature.getProject())); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); - } - } - - /** - * Close the registry. It needs to be recycled because a class has changed - * and now the new class needs to be accessed. - */ - protected void closeRegistry() { - ProxyFactoryRegistry reg = null; - synchronized (this) { - reg = fRegistry; - fRegistry = null; - try { - // Wipe out the Session properties so that they are recomputed. - getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, null); - getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, null); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.INFO); - } - } - if (reg != null) { - reg.removeRegistryListener(registryListener); - reg.terminateRegistry(); - } - } - - private static final String PI_CLASS = "class"; //$NON-NLS-1$ - - /** - * Using the given configuration info, compute the BeanInfo config info needed. This sets the - * session properties BEANINFO_CONTRIBUTORS_SESSION_KEY and CONFIG_INFO_SESSION_KEY. - * - * @param info - * @throws CoreException - * - * @since 1.1.0 - */ - public static void computeBeanInfoConfigInfo(IConfigurationContributionInfo info) throws CoreException { - // First time for this nature, or first time after registry reset. Need to compute the info. - // It is possible for this to be called BEFORE the first usage of BeanInfo. The editor usually - // brings up the editor's registry before it gets anything from BeanInfo. - List contributorsList = new ArrayList(10); - if (!info.getContainerIds().isEmpty()) { - // Run through all of the visible container ids that are applicable and get BeanInfo contributors. - Iterator containerIdItr = info.getContainerIds().values().iterator(); - while (containerIdItr.hasNext()) { - ContainerPaths containerPaths = (ContainerPaths) containerIdItr.next(); - IConfigurationElement[] contributors = BeaninfoPlugin.getPlugin().getContainerIdContributors(containerPaths.getContainerId(), containerPaths.getVisibleContainerPaths()); - for (int i = 0; i < contributors.length; i++) { - try { - Object contributor = contributors[i].createExecutableExtension(PI_CLASS); - if (contributor instanceof IBeanInfoContributor) - contributorsList.add(contributor); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } - } - } - } - - if (!info.getPluginIds().isEmpty()) { - // Run through all of the visible plugin ids that are applicable and get BeanInfo contributors. - Iterator pluginIdItr = info.getPluginIds().entrySet().iterator(); - while (pluginIdItr.hasNext()) { - Map.Entry entry = (Map.Entry) pluginIdItr.next(); - if (((Boolean) entry.getValue()).booleanValue()) { - IConfigurationElement[] contributors = BeaninfoPlugin.getPlugin().getPluginContributors( - (String) entry.getKey()); - if (contributors != null) { - for (int i = 0; i < contributors.length; i++) { - try { - Object contributor = contributors[i].createExecutableExtension(PI_CLASS); - if (contributor instanceof IBeanInfoContributor) - contributorsList.add(contributor); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } - } - } - } - } - } - - // Save it for all beaninfo processing (and configuration processing if they implement proxy configuration contributor). - IBeanInfoContributor[] explicitContributors = (IBeanInfoContributor[]) contributorsList.toArray(new IBeanInfoContributor[contributorsList.size()]); - info.getJavaProject().getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, explicitContributors); - // Save it for override processing. That happens over and over later after all config processing is done. - // Do it last so that if there is a race condition, since this property is a flag to indicate we have data, - // we need to make sure the Beaninfo data is already set at the point we set this. - // We could actually set it twice because of this, but it is the same data, so, so what. - info.getJavaProject().getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, info); - } - - /** - * Get registry, creating it if necessary. - * @return the registry. - * - * @since 1.0.0 - */ - public ProxyFactoryRegistry getRegistry() { - synchronized (this) { - if (fRegistry != null) - return fRegistry; - } - // Now need to start the appropriate job. In another class so that it can handle dynamically checking if - // UI is available to even do this (it maybe not in a UI mode, so then just do it. - CreateRegistryJobHandler.createRegistry(this); - return fRegistry; - } - - private static final long NO_PREMATURE_TERMINATE_TIME = -1; - private int registryPrematureTerminateCount; - private long registryLastPrematureTerminateTime = NO_PREMATURE_TERMINATE_TIME; - - /* - * This is <package-protected> so that only the appropriate create job in this - * package can call it. This is because this must be controlled to only be - * done when build not in progress and serial access. - */ - void createRegistry(IProgressMonitor pm) { - pm.beginTask(BeanInfoAdapterMessages.UICreateRegistryJobHandler_StartBeaninfoRegistry, 100); - if (isRegistryCreated()) { - pm.done(); - return; // It had already been created. Could of been because threads were racing to do the creation, and one got there first. - } - - // Test to see if we have terminated too many times within the last 10 minutes. If we have then don't try again. - synchronized(this) { - if (registryLastPrematureTerminateTime != NO_PREMATURE_TERMINATE_TIME) { - long lastPrematureTerminateInterval = System.currentTimeMillis() - registryLastPrematureTerminateTime; - // Don't try again within 1 sec of last premature terminate. It will still be bad. - // Of if there have been more than 3 and it has been 10 mins since the last try. - if (lastPrematureTerminateInterval < 3*1000 || (registryPrematureTerminateCount > 3 && lastPrematureTerminateInterval < 10 * 60 * 1000)) - return; - } - } - - ProxyFactoryRegistry registry = null; - try { - ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor(); - configurationContributor.setNature(this); - registry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$ - new IConfigurationContributor[] { configurationContributor}, false, new SubProgressMonitor(pm, 100)); - synchronized(this) { - if (!isRegistryCreated()) { - projectCleaned(); - registry.addRegistryListener(registryListener); - fRegistry = registry; - } else { - // It was created while we were creating. So use the current one. Terminate the one just created. Not needed. - registry.terminateRegistry(false); - } - } - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); - } finally { - if (registry == null) { - // It didn't create. Treat as premature terminate. - prematureRegistryTerminate(); - } - pm.done(); - } - } - - /** - * Called by others in package (BeaninfoCacheController) to let know a clean has occured. - * - * TODO this should be package-protected but until in same package as cache controller it is public. - * @since 1.2.0 - */ - public synchronized void projectCleaned() { - // On a clean we will reset the counters. - registryPrematureTerminateCount = 0; - registryLastPrematureTerminateTime = NO_PREMATURE_TERMINATE_TIME; - } - - public synchronized boolean isRegistryCreated() { - return fRegistry != null; - } - - /** - * Check to see if the nature is still valid. If the project has been - * renamed, the nature is still around, but the project has been closed. - * So the nature is now invalid. - * - * @return Is this a valid nature. I.e. is the project still open. - */ - public boolean isValidNature() { - return fProject != null; - } - - /** - * Set the search path onto the registry. - */ - protected void setProxySearchPath(ProxyFactoryRegistry registry, List searchPaths) { - if (searchPaths != null) { - String[] stringSearchPath = (String[]) searchPaths.toArray(new String[searchPaths.size()]); - Utilities.setBeanInfoSearchPath(registry, stringSearchPath); - } else - Utilities.setBeanInfoSearchPath(registry, null); - } - - private static final String ENCODING = "UTF-8"; //$NON-NLS-1$ - static final String sBeaninfos = "beaninfos"; // Root element name //$NON-NLS-1$ - /** - * Get the persistent search path. It is copy. - */ - public BeaninfosDoc getSearchPath() { - BeaninfosDoc bdoc = null; - try { - InputStream property = getSharedProperty(P_BEANINFO_SEARCH_PATH); - if (property != null) { - try { - // Need to reconstruct from the XML format. - Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new InputStreamReader(property, ENCODING))); - Element root = doc.getDocumentElement(); - if (root != null && root.getNodeName().equalsIgnoreCase(sBeaninfos)) { - bdoc = BeaninfosDoc.readEntry(new DOMReader(), root, getProject()); - } - } finally { - try { - property.close(); - } catch (IOException e) { - } - } - } - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); - } catch (Exception e) { - BeaninfoPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, BeaninfoPlugin.PI_BEANINFO_PLUGINID, 0, "", e)); //$NON-NLS-1$ - } - return bdoc; - } - - /** - * Set the persistent search path. No progress monitor. - */ - public void setSearchPath(BeaninfosDoc searchPath) throws CoreException { - setSearchPath(searchPath, null); - } - - /** - * Set the persistent search path with a progress monitor - */ - public void setSearchPath(BeaninfosDoc searchPath, IProgressMonitor monitor) throws CoreException { - String property = null; - if (searchPath != null && searchPath.getSearchpath().length > 0) { - try { - Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); - Element root = doc.createElement(sBeaninfos); // Create Root Element - IBeaninfosDocEntry[] entries = searchPath.getSearchpath(); - for (int i = 0; i < entries.length; i++) - root.appendChild(entries[i].writeEntry(doc, getProject())); // Add to the search path - doc.appendChild(root); // Add Root to Document - StringWriter strWriter = new StringWriter(); - - Result result = new StreamResult(strWriter); - Source source = new DOMSource(doc); - Transformer transformer = TransformerFactory.newInstance().newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ - transformer.transform(source, result); - property = strWriter.toString(); - } catch (TransformerConfigurationException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } catch (TransformerException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } catch (ParserConfigurationException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } catch (FactoryConfigurationError e) { - BeaninfoPlugin.getPlugin().getLogger().log(e, Level.WARNING); - } - } - - if (property != null) { - // If it hasn't changed, don't write it back out. This is so that if the file hasn't - // been checked out and it is the same, we don't want to bother the user. This is because - // we don't know if the user had simply browsed the search path or had actually changed and - // set it back to what it was. In either of those cases it would be a bother to ask the - // user to checkout the file. - InputStream is = getSharedProperty(P_BEANINFO_SEARCH_PATH); - if (is != null) { - try { - try { - InputStreamReader reader = new InputStreamReader(is, ENCODING); - char[] chars = new char[1000]; - StringBuffer oldProperty = new StringBuffer(1000); - int read = reader.read(chars); - while (read != -1) { - oldProperty.append(chars, 0, read); - read = reader.read(chars); - } - if (oldProperty.toString().equals(property)) - return; - } catch (IOException e) { - } // Didn't change. - } finally { - try { - is.close(); - } catch (IOException e) { - } - } - } - setSharedProperty(P_BEANINFO_SEARCH_PATH, property, monitor); - } else - removeSharedProperty(P_BEANINFO_SEARCH_PATH, monitor); - } - - /** - * Return the resource set for all java packages in this nature. - */ - public ResourceSet getResourceSet() { - return javaRSet; - } - - protected void markAllStale() { - // Mark all stale so that the registry will be recycled. - if (fRegistry != null) { - // We have a registry running, we need to indicate recycle is needed. - fSynchronizer.getAdapterFactory().markAllStale(); - // Mark all stale. Next time we need anything it will be recycled. - } - } - - /** - * Compute the file name to use for a given shared property - */ - protected String computeSharedPropertyFileName(QualifiedName qName) { - return qName.getLocalName(); - } - - /** - * Retrieve a shared property on a project. If the property is not defined, answers null. - * Note that it is orthogonal to IResource persistent properties, and client code has to decide - * which form of storage to use appropriately. Shared properties produce real resource files which - * can be shared through a VCM onto a server. Persistent properties are not shareable. - * - */ - protected InputStream getSharedProperty(String propertyFileName) throws CoreException { - IFile rscFile = getProject().getFile(propertyFileName); - if (rscFile.exists()) - return rscFile.getContents(true); - else - return null; - } - - /** - * Record a shared persistent property onto a project. - * Note that it is orthogonal to IResource persistent properties, and client code has to decide - * which form of storage to use appropriately. Shared properties produce real resource files which - * can be shared through a VCM onto a server. Persistent properties are not shareable. - * - * shared properties end up in resource files, and thus cannot be modified during - * delta notifications (a CoreException would then be thrown). - * - */ - protected void setSharedProperty(String propertyName, String value, IProgressMonitor monitor) throws CoreException { - - try { - IFile rscFile = getProject().getFile(propertyName); - InputStream input = new ByteArrayInputStream(value.getBytes(ENCODING)); - // update the resource content - if (rscFile.exists()) { - rscFile.setContents(input, true, false, null); - } else { - rscFile.create(input, true, monitor); - } - } catch (UnsupportedEncodingException e) { - } - } - - /** - * Remove a shared persistent property onto a project. - * Note that it is orthogonal to IResource persistent properties, and client code has to decide - * which form of storage to use appropriately. Shared properties produce real resource files which - * can be shared through a VCM onto a server. Persistent properties are not shareable. - * - * shared properties end up in resource files, and thus cannot be modified during - * delta notifications (a CoreException would then be thrown). - * - */ - protected void removeSharedProperty(String propertyName, IProgressMonitor monitor) throws CoreException { - - IFile rscFile = getProject().getFile(propertyName); - rscFile.delete(true, true, monitor); - } - - /** - * Return a configuration contributor that sets up a vm to allow - * introspection. This will make sure the appropriate paths - * are in the classpath to allow access to the beaninfos, and - * it will setup the beaninfo search path for this project. - */ - public IConfigurationContributor getConfigurationContributor() { - return new ConfigurationContributor(getSearchPath()); - } - - private void prematureRegistryTerminate() { - synchronized(BeaninfoNature.this) { - registryPrematureTerminateCount++; - registryLastPrematureTerminateTime = System.currentTimeMillis(); - } - } - - private static class ConfigurationContributor extends ConfigurationContributorAdapter { - - private BeaninfosDoc doc; - List computedSearchPath; - - // The nature. If the nature is not set then this contributor is one - // used by some other later proxy registry to get the beaninfo classes into their paths. In that case - // we can expect the config info to be in the session variable for our use. Otherwise we will need to - // add it here. Also don't set searchpath stuff if not nature because only the beaninfo one will do introspection. - private BeaninfoNature nature; - - private IConfigurationContributionInfo info; - private IBeanInfoContributor[] explicitContributors; - - public ConfigurationContributor(BeaninfosDoc doc) { - this.doc = doc; - } - - /* - * Set that this is the nature contributor. Not null, means that this is the contributor being - * used to setup the registry for the project's beaninfo nature. null (default) means that this - * is one created to add to some editor's registry. - * - * Note: This MUST be set before initialize is called or it will not work correctly. If not set, it - * will be considered not for BeanInfo nature directly. - */ - public void setNature(BeaninfoNature nature) { - this.nature = nature; - if (nature != null) - computedSearchPath = new ArrayList(3); // We will be gathering this info. - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IConfigurationContributor#initialize(org.eclipse.jem.internal.proxy.core.IConfigurationContributionInfo) - */ - public void initialize(IConfigurationContributionInfo info) { - this.info = info; - try { - if (info.getJavaProject().getProject().getSessionProperty(CONFIG_INFO_SESSION_KEY) == null) { - // TODO For now we will rebuild for each time we open a registry, but it actually is only needed if a classpath - // changes for some reason. At that point we can get it out of here. - - computeBeanInfoConfigInfo(info); - } - explicitContributors = (IBeanInfoContributor[]) info.getJavaProject().getProject().getSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e); - } - } - - public void contributeClasspaths(final IConfigurationContributionController controller) throws CoreException { - // Contribute for this project - contributeClasspathsForProject(controller, info.getJavaProject().getProject(), doc, true); - - if (!info.getProjectPaths().isEmpty()) { - // Run through all of the visible projects and contribute the classpaths (which come from the BeanInfo docs, if they have any). - IWorkspaceRoot root = info.getJavaProject().getProject().getWorkspace().getRoot(); - Iterator projIter = info.getProjectPaths().entrySet().iterator(); - while (projIter.hasNext()) { - Map.Entry entry = (Map.Entry) projIter.next(); - if (((Boolean) entry.getValue()).booleanValue()) { - IResource res = root.findMember((IPath) entry.getKey()); - if (res instanceof IProject && ((IProject) res).isOpen() && BeaninfoNature.hasRuntime((IProject) res)) - contributeClasspathsForProject(controller, (IProject) res, BeaninfoNature.getRuntime((IProject) res) - .getSearchPath(), false); - } - } - } - - if (!info.getContainerIds().isEmpty()) { - // Run through all of the visible container ids that are applicable. - Iterator containerIdItr = info.getContainerIds().values().iterator(); - while (containerIdItr.hasNext()) { - ContainerPaths containerPaths = (ContainerPaths) containerIdItr.next(); - processBeaninfoEntries(BeaninfoPlugin.getPlugin().getContainerIdBeanInfos(containerPaths.getContainerId(), containerPaths.getVisibleContainerPaths()), - controller, info.getJavaProject()); - } - - } - - if (!info.getPluginIds().isEmpty()) { - // Run through all of the visible plugin ids that are applicable. - Iterator pluginIdItr = info.getPluginIds().entrySet().iterator(); - while (pluginIdItr.hasNext()) { - Map.Entry entry = (Map.Entry) pluginIdItr.next(); - if (((Boolean) entry.getValue()).booleanValue()) { - processBeaninfoEntries(BeaninfoPlugin.getPlugin().getPluginBeanInfos((String) entry.getKey()), controller, info.getJavaProject()); - } - } - - } - - if (!info.getContainers().isEmpty()) { - // Run through all of the visible containers that implement IBeanInfoContributor and ask them for the contributions. - Iterator containerItr = info.getContainers().entrySet().iterator(); - while (containerItr.hasNext()) { - Map.Entry entry = (Map.Entry) containerItr.next(); - if (((Boolean) entry.getValue()).booleanValue()) { - if (entry.getKey() instanceof IBeanInfoContributor) - processBeaninfoEntries(((IBeanInfoContributor) entry.getKey()).getBeanInfoEntryContributions(info), - controller, info.getJavaProject()); - } - } - - } - - // And finally run through the explicit contributors. - for (int i = 0; i < explicitContributors.length; i++) { - final IBeanInfoContributor contributor = explicitContributors[i]; - processBeaninfoEntries(contributor.getBeanInfoEntryContributions(info), controller, info.getJavaProject()); - if (contributor instanceof IConfigurationContributor) { - SafeRunner.run(new ISafeRunnable() { - public void handleException(Throwable exception) { - // do nothing. by default platform logs. - } - - public void run() throws Exception {; - if (contributor instanceof IConfigurationContributor) - ((IConfigurationContributor) contributor).contributeClasspaths(controller); - } - }); - } - } - - // Add the common to the end of the classpath. (Since we are now a jarred plugin, the common is not the plugin jar itself). - controller.contributeClasspath(BeaninfoPlugin.getPlugin().getBundle(), (IPath) null, IConfigurationContributionController.APPEND_USER_CLASSPATH, false); //$NON-NLS-1$ - - // Add the beaninfovm.jar and any nls to the end of the classpath. - controller.contributeClasspath(BeaninfoPlugin.getPlugin().getBundle(), "vm/beaninfovm.jar", IConfigurationContributionController.APPEND_USER_CLASSPATH, true); //$NON-NLS-1$ - } - - private IClasspathEntry get(IClasspathEntry[] array, SearchpathEntry se) { - for (int i = 0; i < array.length; i++) { - if (array[i].getEntryKind() == se.getKind() && array[i].getPath().equals(se.getPath())) - return array[i]; - } - return null; - } - - private static final IBeaninfosDocEntry[] EMPTY_ENTRIES = new IBeaninfosDocEntry[0]; - - /* - * Contribute classpaths for the specified project. If doc is passed in, then this is the top level and - * all should be added. If no doc, then this is pre-req'd project, and then we will handle exported entries only. - */ - protected void contributeClasspathsForProject( - IConfigurationContributionController controller, - IProject project, - BeaninfosDoc doc, - boolean toplevelProject) - throws CoreException { - - IJavaProject jProject = JavaCore.create(project); - IClasspathEntry[] rawPath = jProject.getRawClasspath(); - - // Search path of this project - IBeaninfosDocEntry[] entries = (doc != null) ? doc.getSearchpath() : EMPTY_ENTRIES; - - for (int i = 0; i < entries.length; i++) { - IBeaninfosDocEntry entry = entries[i]; - if (entry instanceof BeaninfoEntry) { - BeaninfoEntry be = (BeaninfoEntry) entry; - if (toplevelProject || be.isExported()) { - // First project or this is an exported beaninfo, so we process it. - processBeaninfoEntry(be, controller, jProject); - } - } else if (nature != null){ - // Just a search path entry. There is no beaninfo jar to pick up. - // We have a nature, so we process search path. - SearchpathEntry se = (SearchpathEntry) entry; - if (!toplevelProject) { - // We are in a nested project, find the raw classpath entry to see - // if this entry is exported. Only do it if exported. (Note: exported is only used on non-source. Source are always exported). - IClasspathEntry cpe = get(rawPath, se); - if (cpe == null || (cpe.getEntryKind() != IClasspathEntry.CPE_SOURCE && !cpe.isExported())) { - continue; // Not exist or not exported, so we don't want it here either. - } - } - - String pkg = se.getPackage(); - if (pkg != null) { - // Explicit search path - if (!computedSearchPath.contains(pkg)) - computedSearchPath.add(pkg); - } else { - // We no longer allow this, but just to be on safe side we test for it. - } - } - } - } - - protected void processBeaninfoEntries( - BeaninfoEntry[] entries, - IConfigurationContributionController controller, - IJavaProject javaProject) - throws CoreException { - if (entries != null) { - for (int i = 0; i < entries.length; i++) - processBeaninfoEntry(entries[i], controller, javaProject); - } - } - - protected void processBeaninfoEntry( - BeaninfoEntry entry, - IConfigurationContributionController controller, - IJavaProject javaProject) - throws CoreException { - Object[] cps = entry.getClasspath(javaProject); - for (int j = 0; j < cps.length; j++) { - Object cp = cps[j]; - if (cp instanceof IProject) - controller.contributeProject((IProject) cp); - else if (cp instanceof String) - controller.contributeClasspath(ProxyLaunchSupport.convertStringPathToURL((String) cp), IConfigurationContributionController.APPEND_USER_CLASSPATH); - else if (cp instanceof IPath) { - IPath path = (IPath) cp; - Bundle bundle = Platform.getBundle(path.segment(0)); - if (bundle != null) - controller.contributeClasspath(bundle, path.removeFirstSegments(1), IConfigurationContributionController.APPEND_USER_CLASSPATH, true); - } - } - - if (nature != null) { - // Now add in the package names. - SearchpathEntry[] sees = entry.getSearchPaths(); - for (int j = 0; j < sees.length; j++) { - SearchpathEntry searchpathEntry = sees[j]; - if (!computedSearchPath.contains(searchpathEntry.getPackage())) - computedSearchPath.add(searchpathEntry.getPackage()); - } - } - } - - public void contributeToConfiguration(final ILaunchConfigurationWorkingCopy config) { - for (int i = 0; i < explicitContributors.length; i++) { - final int ii = i; - SafeRunner.run(new ISafeRunnable() { - public void handleException(Throwable exception) { - // do nothing. by default platform logs. - } - - public void run() throws Exception { - IBeanInfoContributor contributor = explicitContributors[ii]; - if (contributor instanceof IConfigurationContributor) - ((IConfigurationContributor) contributor).contributeToConfiguration(config); - } - }); - } - } - - public void contributeToRegistry(final ProxyFactoryRegistry registry) { - if (nature != null) - nature.setProxySearchPath(registry, computedSearchPath); - for (int i = 0; i < explicitContributors.length; i++) { - final int ii = i; - SafeRunner.run(new ISafeRunnable() { - public void handleException(Throwable exception) { - // do nothing. by default platform logs. - } - - public void run() throws Exception { - IBeanInfoContributor contributor = explicitContributors[ii]; - if (contributor instanceof IConfigurationContributor) - ((IConfigurationContributor) contributor).contributeToRegistry(registry); - } - }); - } - } - } - - -} |