| /******************************************************************************* |
| * Copyright (c) 2003, 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.core; |
| /* |
| |
| |
| */ |
| import java.util.Iterator; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.*; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| |
| import org.eclipse.jem.internal.beaninfo.*; |
| import org.eclipse.jem.internal.beaninfo.adapters.BeaninfoNature; |
| import org.eclipse.jem.internal.beaninfo.adapters.BeaninfoProxyConstants; |
| import org.eclipse.jem.internal.java.adapters.ReflectionAdaptor; |
| import org.eclipse.jem.internal.proxy.core.*; |
| import org.eclipse.jem.java.*; |
| |
| /** |
| * Beaninfo (introspection) utilities methods |
| */ |
| |
| public final class Utilities { |
| |
| private Utilities() { |
| } |
| |
| /** |
| * Utility to return the class as a JavaClass. If it actually is a JavaType this will |
| * fail with a ClassCastException. |
| * @param className |
| * @param rset |
| * @return java class |
| * |
| * @throws ClassCastException if not a java class, but instead a java primitive. |
| * @since 1.1.0 |
| */ |
| public static JavaClass getJavaClass(String className, ResourceSet rset) { |
| return (JavaClass) getJavaType(className, rset); |
| } |
| |
| /** |
| * Utility to return the class as a JavaHelpers. |
| * |
| * @param className |
| * @param rset |
| * @return java helpers. |
| * |
| * @since 1.1.0 |
| */ |
| public static JavaHelpers getJavaType(String className, ResourceSet rset) { |
| return (JavaHelpers) rset.getEObject(getJavaClassURI(className), true); |
| } |
| |
| /** |
| * Create a URI to the given classname. |
| * <p> |
| * Note: It must be in normal form, i.e. fully-qualified, if primitive spelled out (e.g. "int" not I), and if |
| * arrays it must readable form (e.g. "java.lang.String[]" and not "[Ljava.lang.String;"). |
| * |
| * @param className |
| * @return |
| * |
| * @since 1.1.0 |
| */ |
| public static URI getJavaClassURI(String className) { |
| return JavaRefFactory.eINSTANCE.createTypeURI(className); |
| } |
| |
| /** |
| * Utility to return the EClassifier from the given IBeanTypeProxy. |
| */ |
| public static EClassifier getJavaClass(IBeanTypeProxy type, ResourceSet rset) { |
| if (type != null) { |
| return getJavaType(type.getFormalTypeName(), rset); |
| } else |
| return null; |
| } |
| |
| /** |
| * Utility to return the Method from the given IMethodProxy. |
| */ |
| public static Method getMethod(IMethodProxy method, ResourceSet rset) { |
| return method != null ? (Method) rset.getEObject(URI.createURI(getMethodURL(method)), true) : null; |
| } |
| |
| /** |
| * Answer the URL String for Method from the given IMethodProxy |
| */ |
| public static String getMethodURL(IMethodProxy method) { |
| String className = method.getClassType().getTypeName(); |
| IBeanTypeProxy[] parms = method.getParameterTypes(); |
| String[] parmTypes = parms.length > 0 ? new String[parms.length] : null; |
| for (int i = 0; i < parms.length; i++) { |
| parmTypes[i] = parms[i].getFormalTypeName(); |
| } |
| return computeMethodURL(className, method.getName(), parmTypes); |
| } |
| |
| protected static String computeMethodURL(String fullyQualifiedClassName, String methodName, String[] parmTypes) { |
| int classStart = fullyQualifiedClassName.lastIndexOf('.'); |
| StringBuffer url = new StringBuffer(50); |
| url.append("java:/"); //$NON-NLS-1$ |
| if (classStart > -1) |
| url.append(fullyQualifiedClassName.substring(0, classStart)); |
| url.append('#'); |
| url.append(computeMethodID(fullyQualifiedClassName.substring(classStart + 1), methodName, parmTypes)); |
| return url.toString(); |
| } |
| |
| protected static String computeFieldURL(String fullyQualifiedClassName, String fieldName) { |
| int classStart = fullyQualifiedClassName.lastIndexOf('.'); |
| StringBuffer url = new StringBuffer(50); |
| url.append("java:/"); //$NON-NLS-1$ |
| if (classStart > -1) |
| url.append(fullyQualifiedClassName.substring(0, classStart)); |
| url.append('#'); |
| url.append(fullyQualifiedClassName.substring(classStart + 1)); |
| url.append(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER); |
| url.append(fieldName); |
| return url.toString(); |
| } |
| |
| /** |
| * Return the field uri for the given classname, fieldname. |
| * @param fullyQualifiedClassName |
| * @param fieldName |
| * @return |
| * |
| * @since 1.1.0 |
| */ |
| public static URI getFieldURI(String fullyQualifiedClassName, String fieldName) { |
| return URI.createURI(computeFieldURL(fullyQualifiedClassName, fieldName)); |
| } |
| /** |
| * Return the method uri for the given classname, methodname, parm types. |
| * @param fullyQualifiedClassName |
| * @param methodName |
| * @param parmTypes <code>null</code> if there are no parms. |
| * @return |
| * |
| * @since 1.1.0 |
| */ |
| public static URI getMethodURI(String fullyQualifiedClassName, String methodName, String[] parmTypes) { |
| return URI.createURI(computeMethodURL(fullyQualifiedClassName, methodName, parmTypes)); |
| } |
| |
| /** |
| * Turn it into an URI. |
| */ |
| public static URI getMethodURI(IMethodProxy method) { |
| return URI.createURI(getMethodURL(method)); |
| } |
| |
| /** |
| * Utility to compute the Java Modeling METHODID from method declaring class name, |
| * method name, and parameter class names. |
| */ |
| public static String computeMethodID(String className, String methodName, String[] parameterTypes) { |
| StringBuffer out = new StringBuffer(50); |
| out.append(className); |
| out.append(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER); |
| out.append(methodName); |
| out.append(ReflectionAdaptor.C_METHOD_PARM_DELIMITER); |
| if (parameterTypes != null) |
| for (int i = 0; i < parameterTypes.length; i++) { |
| out.append(parameterTypes[i]); |
| if (i < parameterTypes.length - 1) |
| out.append(ReflectionAdaptor.C_PARM_PARM_DELIMITER); |
| } |
| if (className.equals(methodName)) |
| out.append(ReflectionAdaptor.S_CONSTRUCTOR_TOKEN); //It's a constructor |
| return out.toString(); |
| } |
| |
| /** |
| * Utility to retrieve the BeanDecorator. |
| */ |
| public static BeanDecorator getBeanDecorator(EModelElement model) { |
| return (BeanDecorator) getDecorator(model, BeanDecorator.class); |
| } |
| /** |
| * Utility to retrieve a decorator of the specified class. |
| */ |
| public static EAnnotation getDecorator(EModelElement model, Class decoratorClass) { |
| Iterator itr = model.getEAnnotations().iterator(); |
| while (itr.hasNext()) { |
| EAnnotation decr = (EAnnotation) itr.next(); |
| if (decoratorClass.isInstance(decr)) |
| return decr; |
| } |
| return null; |
| } |
| |
| /** |
| * Utility to retrieve the EventSetDecorator. |
| */ |
| public static EventSetDecorator getEventSetDecorator(EModelElement model) { |
| return (EventSetDecorator) getDecorator(model, EventSetDecorator.class); |
| } |
| |
| /** |
| * Utility to retrieve the MethodDecorator. |
| */ |
| public static MethodDecorator getMethodDecorator(EModelElement model) { |
| return (MethodDecorator) getDecorator(model, MethodDecorator.class); |
| } |
| |
| /** |
| * Utility to retrieve the PropertyDecorator. |
| */ |
| public static PropertyDecorator getPropertyDecorator(EModelElement model) { |
| return (PropertyDecorator) getDecorator(model, PropertyDecorator.class); |
| } |
| |
| /** |
| * Utility to return an iterator on the list which will return the property decorators |
| * of only the properties in the EList passed in. If the property does not have a |
| * property decorator, then it is not a beaninfo property. |
| */ |
| public static Iterator getPropertiesIterator(final EList properties) { |
| return new Iterator() { |
| private Iterator itr = properties.iterator(); |
| private boolean hasNext = true; |
| private PropertyDecorator next; |
| { |
| findNext(); |
| } |
| public boolean hasNext() { |
| return hasNext; |
| } |
| |
| public Object next() { |
| PropertyDecorator temp = next; |
| findNext(); |
| return temp; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private void findNext() { |
| while (itr.hasNext()) { |
| EModelElement nextOne = (EModelElement) itr.next(); |
| next = getPropertyDecorator(nextOne); |
| if (next != null) { |
| return; |
| } |
| } |
| hasNext = false; |
| } |
| }; |
| } |
| |
| /** |
| * Utility to return an iterator on the list which will return the EventSet decorators |
| * of only the BeanEvents in the EList passed in. |
| */ |
| public static Iterator getEventSetsIterator(final EList events) { |
| return new Iterator() { |
| private Iterator itr = events.iterator(); |
| private boolean hasNext = true; |
| private EventSetDecorator next; |
| { |
| findNext(); |
| } |
| public boolean hasNext() { |
| return hasNext; |
| } |
| |
| public Object next() { |
| EventSetDecorator temp = next; |
| findNext(); |
| return temp; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private void findNext() { |
| while (itr.hasNext()) { |
| EModelElement nextOne = (EModelElement) itr.next(); |
| next = getEventSetDecorator(nextOne); |
| if (next != null) { |
| return; |
| } |
| } |
| hasNext = false; |
| } |
| }; |
| } |
| |
| /** |
| * Utility to return an iterator on the list which will return the Method decorators |
| * of only the Methods in the EList passed in. |
| */ |
| public static Iterator getMethodsIterator(final EList methods) { |
| return new Iterator() { |
| private Iterator itr = methods.iterator(); |
| private boolean hasNext = true; |
| private MethodDecorator next; |
| { |
| findNext(); |
| } |
| public boolean hasNext() { |
| return hasNext; |
| } |
| |
| public Object next() { |
| MethodDecorator temp = next; |
| findNext(); |
| return temp; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private void findNext() { |
| while (itr.hasNext()) { |
| EModelElement nextOne = (EModelElement) itr.next(); |
| next = getMethodDecorator(nextOne); |
| if (next != null) { |
| return; |
| } |
| } |
| hasNext = false; |
| } |
| }; |
| } |
| |
| /** |
| * Get the search path from the remote vm. |
| * |
| * Note: This shouldn't be used when working with a BeaninfoNature. Use the |
| * accessors taking the nature instead. Otherwise there will be inconsistencies since the search path won't be |
| * saved across invocations of the workspace if it is not updated through the nature). |
| */ |
| public static IArrayBeanProxy getBeanInfoSearchPath(ProxyFactoryRegistry registry) { |
| BeaninfoProxyConstants biconstants = BeaninfoProxyConstants.getConstants(registry); |
| if (biconstants != null) |
| return (IArrayBeanProxy) biconstants |
| .getGetBeanInfoSearchPathProxy() |
| .invokeCatchThrowableExceptions( |
| null); |
| else |
| return null; |
| } |
| |
| /** |
| * Set the search path to the array of strings passed in on the remote vm. |
| * |
| * Note: This shouldn't be used when working with a BeaninfoNature. Use the |
| * accessors taking the nature instead. Otherwise there will be inconsistencies since the search path won't be |
| * saved across invocations of the workspace if it is not updated through the nature). |
| */ |
| public static void setBeanInfoSearchPath(ProxyFactoryRegistry registry, String[] paths) { |
| |
| try { |
| BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry); |
| if (biConstants != null) { |
| JavaStandardBeanProxyConstants jConstants = JavaStandardBeanProxyConstants.getConstants(registry); |
| IStandardBeanProxyFactory proxyFactory = registry.getBeanProxyFactory(); |
| IArrayBeanProxy newPath = proxyFactory.createBeanProxyWith(jConstants.getStringType(), paths != null ? paths.length : 0); |
| if (paths != null) |
| for (int i = 0; i < paths.length; i++) |
| newPath.set(proxyFactory.createBeanProxyWith(paths[i]), i); |
| biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath); |
| } |
| } catch (ThrowableProxy e) { |
| } |
| } |
| |
| /** |
| * From the Beaninfo Nature, insert a path to the beaninfo path at the given index, -1 means at the end. |
| * If index is larger than the current path, it will also add at the end. |
| */ |
| public static void insertBeanInfoSearchPath(BeaninfoNature nature, IBeaninfosDocEntry path, int index) throws CoreException { |
| BeaninfosDoc infoPath = nature.getSearchPath(); |
| IBeaninfosDocEntry[] oldPath = infoPath.getSearchpath(); |
| |
| IBeaninfosDocEntry[] newPath = new IBeaninfosDocEntry[oldPath.length + 1]; |
| |
| if (index == -1 || index >= oldPath.length) { |
| // At the end or past end |
| System.arraycopy(oldPath, 0, newPath, 0, oldPath.length); |
| newPath[oldPath.length] = path; |
| } else { |
| // In the middle |
| System.arraycopy(oldPath, 0, newPath, 0, index); |
| newPath[index] = path; |
| System.arraycopy(oldPath, index, newPath, index + 1, oldPath.length - index); |
| } |
| |
| infoPath.setSearchpath(newPath); |
| nature.setSearchPath(infoPath); |
| } |
| |
| /** |
| * Insert a path to the beaninfo path at the given index, -1 means at the end. |
| * If index is larger than the current path, it will also add at the end. |
| * |
| * Note: This shouldn't be used when working with a BeaninfoNature. Use the |
| * accessors taking the nature instead. Otherwise there will be inconsistencies since the search path won't be |
| * saved across invocations of the workspace if it is not updated through the nature). |
| */ |
| public static void insertBeanInfoSearchPath(ProxyFactoryRegistry registry, String path, int index) { |
| try { |
| BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry); |
| if (biConstants != null) { |
| IArrayBeanProxy infoPath = (IArrayBeanProxy) biConstants.getGetBeanInfoSearchPathProxy().invoke(null); |
| int pathLength = infoPath.getLength(); |
| IStandardBeanProxyFactory proxyFactory = registry.getBeanProxyFactory(); |
| IArrayBeanProxy newPath = proxyFactory.createBeanProxyWith(infoPath.getTypeProxy(), pathLength + 1); |
| IBeanProxy stringProxy = proxyFactory.createBeanProxyWith(path); |
| JavaStandardBeanProxyConstants constants = JavaStandardBeanProxyConstants.getConstants(registry); |
| if (index == -1 || index >= pathLength) { |
| // At the end or past end |
| constants.arraycopy(infoPath, 0, newPath, 0, infoPath.getLength()); |
| newPath.set(stringProxy, pathLength); |
| } else { |
| // In the middle |
| constants.arraycopy(infoPath, 0, newPath, 0, index); |
| newPath.set(stringProxy, index); |
| constants.arraycopy(infoPath, index, newPath, index + 1, pathLength - index); |
| } |
| biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath); |
| } |
| } catch (ThrowableProxy e) { |
| } |
| } |
| |
| /** |
| * From the Beaninfo Nature, remove the specified path from the beaninfo search path. |
| * Not an error if not found. |
| */ |
| public static void removeBeanInfoPath(BeaninfoNature nature, IBeaninfosDocEntry path) throws CoreException { |
| BeaninfosDoc infoPath = nature.getSearchPath(); |
| IBeaninfosDocEntry[] oldPath = infoPath.getSearchpath(); |
| |
| for (int i = 0; i < oldPath.length; i++) { |
| if (path.equals(oldPath[i])) { |
| // We found it, so remove it. |
| IBeaninfosDocEntry[] newPath = new IBeaninfosDocEntry[oldPath.length - 1]; |
| System.arraycopy(oldPath, 0, newPath, 0, i); |
| if (i < oldPath.length - 1) |
| System.arraycopy(oldPath, i + 1, newPath, i, oldPath.length - i - 1); |
| infoPath.setSearchpath(newPath); |
| nature.setSearchPath(infoPath); |
| return; |
| } |
| } |
| } |
| |
| /** |
| * Remove the specified path from the beaninfo search path. |
| * Not an error if not found. |
| * |
| * Note: This shouldn't be used when working with a BeaninfoNature. Use the |
| * accessors taking the nature instead. Otherwise there will be inconsistencies since the search path won't be |
| * saved across invocations of the workspace if it is not updated through the nature). |
| */ |
| public static void removeBeanInfoPath(ProxyFactoryRegistry registry, String path) { |
| try { |
| BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry); |
| if (biConstants != null) { |
| IArrayBeanProxy infoPath = (IArrayBeanProxy) biConstants.getGetBeanInfoSearchPathProxy().invoke(null); |
| int pathLength = infoPath.getLength(); |
| for (int i = 0; i < pathLength; i++) { |
| IStringBeanProxy aPath = (IStringBeanProxy) infoPath.get(i); |
| if (path.equals(aPath.stringValue())) { |
| // We found it, so remove it. |
| IArrayBeanProxy newPath = registry.getBeanProxyFactory().createBeanProxyWith(infoPath.getTypeProxy(), pathLength - 1); |
| JavaStandardBeanProxyConstants constants = JavaStandardBeanProxyConstants.getConstants(registry); |
| constants.arraycopy(infoPath, 0, newPath, 0, i); |
| if (i < pathLength - 1) |
| constants.arraycopy(infoPath, i + 1, newPath, i, pathLength - i - 1); |
| biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath); |
| return; |
| } |
| } |
| } |
| } catch (ThrowableProxy e) { |
| } |
| }; |
| |
| } |