Edit D:\app\Administrator\product\11.2.0\dbhome_1\ide\src\javax\ide\extension\DynamicHook.java
/* * Copyright 2005 by Oracle USA * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A. * All rights reserved. */ package javax.ide.extension; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.logging.Level; import javax.ide.extension.spi.Stack; /** * An implementation of <tt>ExtensionHook</tt> that automatically populates * model objects using reflection. */ public class DynamicHook extends ExtensionHook { public final String sApplicationObjectKey = DynamicHook.class.getName() + ".appObjectKey"; private static final String ATTRIBUTE_CLASS = "class"; private static final String SET_METHOD_PREFIX = "set"; private static final String ADD_METHOD_PREFIX = "add"; private static final Class[] sObjectParamTypes = { Object.class }; private static final Class[] sStringParamTypes = { String.class }; /** * This stack references the application objects currently in scope. After * creation, an application object is pushed onto the stack. When that * complex element goes out of scope, the object is popped from the stack. */ private final Stack _applicationObjectStack = new Stack(); /** * This stack references a verdict on whether the element in scope is complex * or simple. When the element goes out of scope, the verdict on the parent * element is available at the top of this stack. */ private final Stack _complexTypeIndicatorStack = new Stack(); /** * If non-null, this classloader is passed to all calls to Class.newInstance() * , otherwise the current thread context classloader is used. */ private ClassLoader _classLoader; /** * A list of registered {@link ElementTypeResolver}s which may be queried for * the runtime type corresponding to an xml element. */ private final List _resolvers = new ArrayList(5); public DynamicHook(Object rootObject) { // Push the root object into first place on the stack. _applicationObjectStack.push(rootObject); } public DynamicHook(Object rootObject, ClassLoader classLoader) { this(rootObject); _classLoader = classLoader; } public DynamicHook( Object rootObject, ClassLoader classLoader, ElementTypeResolver resolver) { this(rootObject, classLoader); _resolvers.add(resolver); } public void registerElementTypeResolver(ElementTypeResolver resolver) { _resolvers.add(resolver); } public void start(ElementStartContext context) { Class runtimeType = getRuntimeType(context); _complexTypeIndicatorStack.push(new boolean[] { runtimeType != null ? true : false }); if (runtimeType != null) { // Retrieve the application object for the complex element. Object o = getApplicationObject(runtimeType, context); // Pre initialization hook. invokePreInitialize(_applicationObjectStack.peek(), o); // Push the application object onto the stack so that it becomes the // object in scope for child elements. _applicationObjectStack.push(o); // Push the application object onto the context map in scope. This makes // it available globally under the sApplicationObjectKey key. Note: // keeping a separate stack of app objects maintains the integrity of the // dynamic handler instance, since child handlers are at liberty to remove // an object from the context map. context.getScopeData().put(sApplicationObjectKey, o); // Additional complex element start behaviour, e.g. specialized attribute // handling. handleComplexElementStart(o, context); } else { // Additional simple element start behaviour, e.g. specialized attribute // handling. handleSimpleElementStart(context); } } public void end(ElementEndContext context) { boolean isComplex = ((boolean[])_complexTypeIndicatorStack.pop())[0]; if (isComplex) { // Reference the child object. Object child = _applicationObjectStack.pop(); // Post initialization hook. invokePostInitialize(child); // Attach the child and parent objects. attachObject(_applicationObjectStack.peek(), child, context); // Hook for additional complex element end behaviour (none by default). handleComplexElementEnd(context); } else { // Attach any simple element data to the application object in scope. attachData(_applicationObjectStack.peek(), context.getText(), context); // Hook for additional simple element end behaviour (none by default). handleSimpleElementEnd(context); } } protected void handleComplexElementStart( Object applicationObject, ElementStartContext context) { // This basic implementation only knows about the 'class' attribute for // complex elements. However, specializations may override at this point // to plug in additional behaviour. } protected void handleComplexElementEnd(ElementEndContext context) { // This implementation takes no more action on ending of a complex element // after the child object has been attached to the parent object. } protected void handleSimpleElementStart(ElementStartContext context) { // This basic implementation ignores all attributes for simple elements. // However, specializations may override at this point to plug in additional // behaviour. } protected void handleSimpleElementEnd(ElementEndContext context) { // This implementation takes no more action on ending of a simple element // after the child data has been attached to the object in scope. } protected Class getRuntimeType(ElementStartContext context) { // First, interrogate the 'class' attribute. Failing that, interrogate the // registered resolvers in reverse order. Class type = null; String classAttribute = context.getAttributeValue(ATTRIBUTE_CLASS); if (classAttribute != null) { try { type = Class.forName(classAttribute, true, _classLoader != null ? _classLoader : Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException cnfe) { log( context, Level.SEVERE, "Unable to load class: " + classAttribute ); } } else { ListIterator it = _resolvers.listIterator(_resolvers.size()); while (it.hasPrevious() && type == null) { type = ((ElementTypeResolver)it.previous()).resolveType( context.getElementName() ); } } return type; } protected Object getApplicationObject( Class runtimeType, ElementStartContext context) { // In this simple implementation, the only information needed to retrieve // the application object is its type, however extra context is provided // in this method for the benefit of specializations. try { return runtimeType.newInstance(); } catch (Exception e) { log( context, Level.SEVERE, "Unable to instantiate class: " + runtimeType.getName() ); e.printStackTrace(); return null; } } protected void attachObject( Object parent, Object child, ElementEndContext context) { // Find the relevant setXXX(Object) or addXXX(Object) method on the // parent application object. Method m = findMethod(context, parent, context.getElementName().getLocalName(), sObjectParamTypes); // Dynamically invoke the target method, passing the child object as the // parameter to the target method. try { m.invoke(parent, new Object[] {child}); } catch (InvocationTargetException ite) { StringBuffer b = new StringBuffer(200); b.append("Could not attach child object: ").append(child.toString()); b.append(" to parent: ").append(parent.toString()); b.append(". Root cause: "); b.append(ite.getTargetException().getClass().getName()).append(": "); b.append(ite.getTargetException().getMessage()); log( context, Level.SEVERE, b.toString() ); } catch (Exception e) { StringBuffer b = new StringBuffer(200); b.append("Could not attach child object: ").append(child.toString()); b.append(" to parent: ").append(parent.toString()); b.append(". Root cause: "); b.append(e.getClass().getName()).append(": ").append(e.getMessage()); log( context, Level.SEVERE, b.toString() ); } } protected void attachData( Object parent, String data, ElementEndContext context) { // Find the appropriate setXXX(String) method. Method m = findMethod(context, parent, context.getElementName().getLocalName(), sStringParamTypes); // Invoke the method. try { m.invoke(parent, new Object[] { data }); } catch (InvocationTargetException ite) { log( context, Level.SEVERE, "Unable to attach data '" + data + "' for simple element " + context.getElementName().getLocalName() ); ite.getTargetException().printStackTrace(); } catch (Exception e) { log( context, Level.SEVERE, "Unable to attach data '" + data + "' for simple element " + context.getElementName().getLocalName()); e.printStackTrace(); } } protected void invokePreInitialize(Object child, Object parent) { // TODO: Define a preinit hook? // E.g: ((InitializableXMLObject)child).preInit(parent); } protected void invokePostInitialize(Object o) { // TODO: Define a postInit hook. // E.g: ((InitializableXMLObject)o).postInit(); } protected Method findMethod(ElementContext context, Object o, String elementName, Class[] paramTypes) { String methodName; try { methodName = getMethodName(SET_METHOD_PREFIX, elementName); return o.getClass().getMethod(methodName, paramTypes); } catch (NoSuchMethodException nsme) { try { methodName = getMethodName(ADD_METHOD_PREFIX, elementName); return o.getClass().getMethod(methodName, paramTypes); } catch (NoSuchMethodException nme) { log( context, Level.SEVERE, "Class " + o.getClass().getName() + " has no set or add method for element named " + elementName ); nme.printStackTrace(); } } return null; } protected String getMethodName(String prefix, String elementName) { char[] name = new char[prefix.length() + elementName.length()]; for (int i = 0; i < prefix.length(); i++) { name[i] = prefix.charAt(i); } boolean nextUpper = true; int nameIndex = prefix.length(); for (int i = 0; i < elementName.length(); i++) { if (Character.isJavaIdentifierPart(elementName.charAt(i))) { if (nextUpper) { name[nameIndex] = Character.toUpperCase(elementName.charAt(i)); nextUpper = false; } else { name[nameIndex] = elementName.charAt(i); } nameIndex++; } else { nextUpper = true; } } return new String(name).trim(); } /** * An object which can resolve an ElementName into a Class type for that * element. */ public static interface ElementTypeResolver { /** * Resolves a fully-qualified element name to a runtime type which is capable * of consuming information in child elements as laid out by the rules * defined by {@link DynamicHook}. * * @param elementName the fully qualified name of the element to be * resolved. * @return a {@link java.lang.Class} representing the runtime type capable * of consuming the xml, or <code>null</code> if no matching type is found. */ public Class resolveType( ElementName elementName ); } }
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de