| /* |
| |
| Derby - Class org.apache.derby.catalog.Java5SystemProcedures |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| |
| package org.apache.derby.catalog; |
| |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.sql.SQLException; |
| |
| import org.apache.derby.iapi.sql.dictionary.OptionalTool; |
| import org.apache.derby.iapi.error.PublicAPI; |
| import org.apache.derby.iapi.error.StandardException; |
| import org.apache.derby.iapi.reference.SQLState; |
| import org.apache.derby.iapi.services.context.Context; |
| import org.apache.derby.iapi.services.context.ContextService; |
| import org.apache.derby.iapi.services.loader.ClassFactory; |
| import org.apache.derby.iapi.services.loader.ClassFactoryContext; |
| |
| /** |
| * <p> |
| * System procedures which run only on Java 5 or higher. |
| * </p> |
| */ |
| public class Java5SystemProcedures |
| { |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // CONSTANTS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** Offsets into arrays in OPTIONAL_TOOLS */ |
| private static final int TOOL_NAME = 0; |
| private static final int TOOL_CLASS_NAME = TOOL_NAME + 1; |
| |
| /** Generic name for all user-supplied tools: the first optional arg is the tool class name */ |
| private static final String CUSTOM_TOOL_CLASS_NAME = "customTool"; |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // STATE |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** Mapping of tool names to their implementing classes for use by SYSCS_REGISTER_TOOL */ |
| private static final String[][] OPTIONAL_TOOLS = new String[][] |
| { |
| { "databaseMetaData", "org.apache.derby.impl.tools.optional.DBMDWrapper" }, |
| { "foreignViews", "org.apache.derby.impl.tools.optional.ForeignDBViews" }, |
| { "luceneSupport", "org.apache.derby.optional.lucene.LuceneSupport" }, |
| { "optimizerTracing", "org.apache.derby.impl.sql.compile.OptimizerTracer" }, |
| { "optimizerTracingViews", "org.apache.derby.impl.sql.compile.OptTraceViewer" }, |
| { "rawDBReader", "org.apache.derby.optional.dump.RawDBReader" }, |
| { "simpleJson", "org.apache.derby.optional.json.SimpleJsonTool" }, |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // PUBLIC BEHAVIOR |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * <p> |
| * Load or unload an optional tool package. If the tool name is the special |
| * CUSTOM_TOOL_CLASS_NAME tool, then the first optionalArg is the name |
| * of a user-supplied class which implements OptionalTool. |
| * </p> |
| * |
| * @param toolName Name of the tool package. |
| * @param register True if the package should be loaded, false otherwise. |
| * @param optionalArgs Tool-specific configuration parameters. |
| */ |
| public static void SYSCS_REGISTER_TOOL |
| ( |
| String toolName, |
| boolean register, |
| String... optionalArgs |
| ) |
| throws SQLException |
| { |
| try { |
| ClassFactoryContext cfc = (ClassFactoryContext) getContext( ClassFactoryContext.CONTEXT_ID ); |
| ClassFactory classFactory = cfc.getClassFactory(); |
| |
| String toolClassName = findToolClassName( toolName, optionalArgs ); |
| OptionalTool tool = null; |
| |
| Class<?> toolClass; |
| try { |
| toolClass = classFactory.loadApplicationClass( toolClassName ); |
| } |
| catch (ClassNotFoundException cnfe) { throw wrap( cnfe ); } |
| |
| if (!OptionalTool.class.isAssignableFrom(toolClass)) { |
| throw badCustomTool(toolClassName); |
| } |
| |
| try { |
| tool = (OptionalTool) toolClass.getConstructor().newInstance(); |
| } |
| catch (InstantiationException ie) { throw wrap( ie ); } |
| catch (IllegalAccessException iae) { throw wrap( iae ); } |
| catch (NoSuchMethodException ie) { throw wrap( ie ); } |
| catch (java.lang.reflect.InvocationTargetException iae) { throw wrap( iae ); } |
| |
| // Strip the custom tool class name from the optional args as necessary |
| if ( CUSTOM_TOOL_CLASS_NAME.equals( toolName ) ) |
| { |
| optionalArgs = stripCustomClassName( optionalArgs ); |
| } |
| |
| if ( register ) { tool.loadTool( optionalArgs ); } |
| else { tool.unloadTool( optionalArgs ); } |
| } |
| catch (StandardException se) { throw PublicAPI.wrapStandardException( se ); } |
| } |
| /** Lookup the class name corresponding to the name of an optional tool */ |
| private static String findToolClassName( String toolName, String... optionalArgs ) throws StandardException |
| { |
| // |
| // For a user-supplied tool, the first optional arg is the name of a user-supplied class |
| // which implements OptionalTool |
| // |
| if ( CUSTOM_TOOL_CLASS_NAME.equals( toolName ) ) |
| { |
| if ( (optionalArgs == null) || (optionalArgs.length == 0) ) |
| { |
| throw badTool( "null" ); |
| } |
| else { return optionalArgs[ 0 ]; } |
| } |
| |
| for ( String[] descriptor : OPTIONAL_TOOLS ) |
| { |
| if ( descriptor[ TOOL_NAME ].equals( toolName ) ) { return descriptor[ TOOL_CLASS_NAME ]; } |
| } |
| |
| throw badTool( toolName ); |
| } |
| private static StandardException badTool( String toolName ) |
| { |
| return StandardException.newException( SQLState.LANG_UNKNOWN_TOOL_NAME, toolName ); |
| } |
| |
| private static StandardException badCustomTool(String className) { |
| return StandardException.newException( |
| SQLState.LANG_UNKNOWN_CUSTOM_TOOL_NAME, className); |
| } |
| |
| /** |
| * <p> |
| * For a custom tool, we strip the first arg from the list of optional args. By |
| * the time we get to this method, it has already been determined that there is |
| * at least one arg and it is the name of a class which implements OptionalTool. |
| * </p> |
| */ |
| private static String[] stripCustomClassName( String... optionalArgs ) |
| { |
| int count = optionalArgs.length - 1; |
| String[] retval = new String[ count ]; |
| |
| for ( int i = 0; i < count; i++ ) { retval[ i ] = optionalArgs[ i + 1 ]; } |
| |
| return retval; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////// |
| // |
| // MINIONS |
| // |
| /////////////////////////////////////////////////////////////////////////////////// |
| |
| private static StandardException wrap( Throwable t ) { return StandardException.plainWrapException( t ); } |
| |
| /** |
| * Privileged lookup of a Context. Must be private so that user code |
| * can't call this entry point. |
| */ |
| private static Context getContext( final String contextID ) |
| { |
| if ( System.getSecurityManager() == null ) |
| { |
| return ContextService.getContext( contextID ); |
| } |
| else |
| { |
| return AccessController.doPrivileged |
| ( |
| new PrivilegedAction<Context>() |
| { |
| public Context run() |
| { |
| return ContextService.getContext( contextID ); |
| } |
| } |
| ); |
| } |
| } |
| |
| } |
| |