📄 subscription.java
字号:
/*Derby - Class org.apache.derbyDemo.vtis.snapshot.SubscriptionLicensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE file distributed withthis 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 withthe License. You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed 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 andlimitations under the License.*/package org.apache.derbyDemo.vtis.snapshot;import java.io.*;import java.lang.reflect.*;import java.sql.*;import java.util.*;import org.apache.derbyDemo.vtis.core.*;/** * <p> * This is the superclass of parameterized subscriptions to foreign data. This * provides the machinery to drop/create a subscription and to refresh it with * the latest foreign data filtered according to the subscription parameters. * </p> * */public abstract class Subscription extends QueryVTIHelper{ /////////////////////////////////////////////////////////////////////////////////// // // CONSTANTS // /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// // // INNER CLASSES // /////////////////////////////////////////////////////////////////////////////////// /** * <p> * This is the state variable used by the logic which creates and refreshes * a Subscription. This state is shared across all of the queries against * the foreign database. * </p> * */ public static final class SubscriptionContext { private SubscriptionSignature _signature; private HashMap<String, String> _parameterValues; private String _connectionURL; public SubscriptionContext( SubscriptionSignature signature, HashMap<String, String> parameterValues, String connectionURL ) { _signature = signature; _parameterValues = parameterValues; _connectionURL = connectionURL; } public SubscriptionSignature getSubscriptionSignature() { return _signature; } public HashMap<String, String> getParameterValues() { return _parameterValues; } public String getConnectionURL() { return _connectionURL; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append( "SubscriptionContext( " ); buffer.append( " signature = " + _signature ); buffer.append( ", parameterValues = " + _parameterValues ); buffer.append( ", connectionURL = " + _connectionURL ); buffer.append( " )" ); return buffer.toString(); } } /////////////////////////////////////////////////////////////////////////////////// // // STATE // /////////////////////////////////////////////////////////////////////////////////// private static HashMap<String, SubscriptionContext> _contexts = new HashMap<String, SubscriptionContext>(); /////////////////////////////////////////////////////////////////////////////////// // // CONSTRUCTORS // /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// // // PUBLIC PROCEDURES // /////////////////////////////////////////////////////////////////////////////////// /** * <p> * Create an empty subscription. You must refresh it later on to actually * populate it with data. This is registered with Derby as the * "createSubscription" procedure. * </p> * */ public static void createSubscription( String subscriptionClassName, String connectionURL ) throws Exception { Class subscriptionClass = Class.forName( subscriptionClassName ); SubscriptionSignature subscriptionSignature = (SubscriptionSignature) subscriptionClass.getAnnotation( SubscriptionSignature.class ); String jdbcDriverName = subscriptionSignature.jdbcDriverName(); String[] subscriptionParameters = subscriptionSignature.parameters(); Method[] methods = subscriptionClass.getMethods(); int methodCount = methods.length; Method candidate = null; int paramCount = subscriptionParameters.length; HashSet<String> parameterMap = new HashSet<String>(); for ( int i = 0; i < paramCount; i++ ) { parameterMap.add( subscriptionParameters[ i ] ); } createContext( subscriptionClassName, null, connectionURL ); try { for ( int i = 0; i < methodCount; i++ ) { candidate = methods[ i ]; if ( isSnapshotQuery( candidate ) ) { createVTIAndEmptyTable( subscriptionClassName, candidate, jdbcDriverName, connectionURL, parameterMap ); } } registerRefreshProcedure( subscriptionSignature ); } finally { dropContext( subscriptionClassName ); } } /** * <p> * Drop a subscription. This is registered with Derby as the * "dropSubscription" procedure. * </p> * */ public static void dropSubscription( String subscriptionClassName ) throws Exception { Class subscriptionClass = Class.forName( subscriptionClassName ); SubscriptionSignature subscriptionSignature = (SubscriptionSignature) subscriptionClass.getAnnotation( SubscriptionSignature.class ); Method[] methods = subscriptionClass.getMethods(); int methodCount = methods.length; Method candidate = null; SnapshotQuery snapshotQueryAnnotation = null; createContext( subscriptionClassName, null, null ); try { for ( int i = 0; i < methodCount; i++ ) { candidate = methods[ i ]; if ( isSnapshotQuery( candidate ) ) { dropVTIAndTable( candidate ); } } unregisterRefreshProcedure( subscriptionSignature ); } finally { dropContext( subscriptionClassName ); } } /** * <p> * Refresh a subscription. This is called by the * refresh procedure whose name is the refreshProcedureName from the * subscription's SubscriptionSignature. The trailing varargs are the * parameter values. * </p> * */ public static void refreshSubscription( String subscriptionClassName, String connectionURL, String... parameterValues ) throws Exception { Class subscriptionClass = Class.forName( subscriptionClassName ); SubscriptionSignature subscriptionSignature = (SubscriptionSignature) subscriptionClass.getAnnotation( SubscriptionSignature.class ); String jdbcDriverName = subscriptionSignature.jdbcDriverName(); String[] parameterNames = subscriptionSignature.parameters(); Method[] methods = subscriptionClass.getMethods(); int methodCount = methods.length; Method candidate = null; ArrayList<Method> snapshotQueries = new ArrayList<Method>(); Connection foreignConnection = getConnection( jdbcDriverName, connectionURL ); Connection localConnection = VTIHelper.getLocalConnection(); boolean oldLocalAutoCommitState = localConnection.getAutoCommit(); createContext( subscriptionClassName, parameterValues, connectionURL ); try { // turn off autocommit so that the whole batch occurs in one transaction foreignConnection.setAutoCommit( false ); localConnection.setAutoCommit( false ); // find all the snapshot queries for ( int i = 0; i < methodCount; i++ ) { candidate = methods[ i ]; if ( isSnapshotQuery( candidate ) ) { snapshotQueries.add( candidate ); } } truncateTables( snapshotQueries ); fillTables( snapshotQueries ); // commit foreign and local transactions foreignConnection.commit(); localConnection.commit(); // return autocommit to its previous state localConnection.setAutoCommit( oldLocalAutoCommitState ); // now release the foreign connection closeConnection( connectionURL ); } finally { dropContext( subscriptionClassName ); } } /////////////////////////////////////////////////////////////////////////////////// // // PROTECTED BEHAVIOR // /////////////////////////////////////////////////////////////////////////////////// /** * <p> * Create a VTI ResultSet. It is assumed that our caller is a * SnapshotQuery-annotated method with no arguments. * </p> * */ protected static ResultSet instantiateSnapshotQueryVTI() throws SQLException { String subscriptionClassName = null; SnapshotQuery annotation = null; try { // look up the method on top of us StackTraceElement[] stack = (new Throwable()).getStackTrace(); StackTraceElement caller = stack[ 1 ]; Class callerClass = Class.forName( caller.getClassName() ); String methodName = caller.getMethodName(); Method method = callerClass.getMethod ( methodName, new Class[] {} ); subscriptionClassName = callerClass.getName(); annotation = method.getAnnotation( SnapshotQuery.class ); } catch (Throwable t) { throw new SQLException( t.getMessage() ); } SubscriptionContext context = getContext( subscriptionClassName, true ); String jdbcDriverName = context.getSubscriptionSignature().jdbcDriverName(); String connectionURL = context.getConnectionURL(); String query = annotation.query(); String[] queryParameterNames = annotation.parameters(); int count = queryParameterNames.length; String[] params = new String[ count ]; HashMap<String, String> parameterValues = context.getParameterValues(); if ( parameterValues != null ) { for ( int i = 0; i < count; i++ ) { params[ i ] = parameterValues.get( queryParameterNames[ i ] ); } } return instantiateVTI( jdbcDriverName, connectionURL, query, params ); } ///////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -