/* * Copyright 2005 by Oracle USA * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A. * All rights reserved. */ package javax.ide.extension.spi; import java.net.URI; import java.util.logging.Level; import javax.ide.extension.ElementName; import javax.ide.extension.ElementStartContext; import javax.ide.extension.ElementVisitor; import javax.ide.extension.ExtensionHook; import javax.ide.net.URIFactory; import javax.ide.net.VirtualFileSystem; import javax.ide.util.MetaClass; /** * The hook-handler-hook implementation. This implementation takes a * DefaultHookVisitorFactory in its constructor and registers * handlers for custom hooks through this factory. */ public class HookHandlerHook extends ExtensionHook { public static final ElementName ELEMENT = new ElementName( MANIFEST_XMLNS, "hook-handler-hook" ); private final DefaultHookVisitorFactory _factory; private final ElementName HOOKHANDLER = new ElementName( MANIFEST_XMLNS, "hook-handler" ); private ElementVisitor _hookHandlerVisitor = new HookHandlerVisitor(); /** * Constructs a new HookHandlerHook. * * @param hookFactory the hook factory. Must not be null. */ public HookHandlerHook( DefaultHookVisitorFactory hookFactory ) { if ( hookFactory == null ) { throw new NullPointerException( "hookFactory is null" ); } _factory = hookFactory; } public void start( ElementStartContext context ) { context.registerChildVisitor( HOOKHANDLER, _hookHandlerVisitor ); } private class HookHandlerVisitor extends ElementVisitor { public void start( ElementStartContext context ) { String tagName = context.getAttributeValue( "tag-name" ); if ( tagName == null || ( tagName = tagName.trim()) == "" ) { log( context, Level.SEVERE, "Missing required attribute 'tag-name'" ); return; } String handlerClass = context.getAttributeValue( "handler-class" ); if ( handlerClass == null || ( handlerClass = handlerClass.trim() ) == "" ) { log( context, Level.SEVERE, "Missing required attribute 'handler-class'" ); return; } String namespace = context.getAttributeValue( "namespace" ); if ( namespace == null || ( namespace = namespace.trim() ) == "" ) { log( context, Level.SEVERE, "Missing required attribute 'namespace'" ); return; } String schemaLocation = context.getAttributeValue( "schema-location" ); if ( schemaLocation != null && schemaLocation.trim().length() > 0 ) { // Attempt to find the schema in the jar. URI sourceUri = context.getExtensionSourceURI(); URI schemaUri = URIFactory.newJarURI( sourceUri, "META-INF/" + schemaLocation.replace( '\\', '/' ) ); if ( !VirtualFileSystem.getVirtualFileSystem().exists( schemaUri ) ) { log( context, Level.SEVERE, "Schema not found: " + VirtualFileSystem.getVirtualFileSystem().getPlatformPathName( schemaUri ) ); schemaLocation = null; } } ElementName elementName = new ElementName( namespace, tagName ); if ( _factory.isNameRegistered( elementName ) ) { // For now we consider this to be an error rather than allowing // handlers to be subverted by downstream extensions. log( context, Level.SEVERE, "A custom hook is already registered for " + elementName.getNamespaceURI()+":"+elementName.getLocalName() ); return; } MetaClass mc = new MetaClass( Thread.currentThread().getContextClassLoader(), handlerClass ); Object hookInstance = null; try { hookInstance = mc.newInstance(); } catch ( ClassNotFoundException cnfe ) { log( context, Level.SEVERE, "Custom hook class "+handlerClass+" not found." ); return; } catch ( InstantiationException ie ) { log( context, Level.SEVERE, "Custom hook class "+handlerClass+ " cannot be instantiated." ); // TODO print these to a logger or somewhere more sensible. ie.printStackTrace(); } catch ( IllegalAccessException iae ) { log( context, Level.SEVERE, "Custom hook class "+handlerClass+ " is not public or does not have a public no argument constructor." ); iae.printStackTrace(); } if ( hookInstance != null ) { try { ExtensionHook hook = (ExtensionHook) hookInstance; _factory.registerHook( elementName, hook ); hook.setSchemaLocation( schemaLocation ); hook.setProvider( getExtension( context ).getID() ); } catch ( ClassCastException cce ) { log( context, Level.SEVERE, "Custom hook class "+handlerClass+ " is not derived from "+ExtensionHook.class.getName() ); } } } } }