Android Open Source - android-sqlite-server Bulk Cursor To Cursor Adaptor






From Project

Back to project page android-sqlite-server.

License

The source code is released under:

Apache License

If you think the Android project android-sqlite-server listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2006 The Android Open Source Project
 *//w  w w  .  j  av  a 2  s . c om
 * Licensed 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 aosp.android.database;

import android.database.AbstractWindowedCursor;
import android.database.ContentObserver;
import android.database.IContentObserver;
import android.database.StaleDataException;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Adapts an {@link IBulkCursor} to a {@link android.database.Cursor} for use in the local process.
 *
 * {@hide}
 */
public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
    private static final String TAG = "BulkCursor";

    // AndroidSQLiteServer-changed
    private static final Method sGetContentObserverMethod;

    private SelfContentObserver mObserverBridge = new SelfContentObserver(this);
    private IBulkCursor mBulkCursor;
    private String[] mColumns;
    private boolean mWantsAllOnMoveCalls;
    private int mCount;

    static {
        try {
            // This is the one area that AndroidSQLiteServer is not currently strictly
            // forward compatible.
            sGetContentObserverMethod = ContentObserver.class.getMethod("getContentObserver");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Unexpected missing method: " +
                    "ContentObserver#getContentObserver");
        }
    }

    /**
     * Initializes the adaptor.
     * Must be called before first use.
     */
    public void initialize(BulkCursorDescriptor d) {
        mBulkCursor = d.cursor;
        mColumns = d.columnNames;
        mRowIdColumnIndex = MoreDatabaseUtils.findRowIdColumnIndex(mColumns);
        mWantsAllOnMoveCalls = d.wantsAllOnMoveCalls;
        mCount = d.count;
        if (d.window != null) {
            setWindow(d.window);
        }
    }

    /**
     * Gets a SelfDataChangeOberserver that can be sent to a remote
     * process to receive change notifications over IPC.
     *
     * @return A SelfContentObserver hooked up to this Cursor
     */
    public IContentObserver getObserver() {
        // BEGIN AndroidSQLiteServer-changed
        try {
            return (IContentObserver)sGetContentObserverMethod.invoke(mObserverBridge);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        // END AndroidSQLiteServer-changed
    }

    private void throwIfCursorIsClosed() {
        if (mBulkCursor == null) {
            throw new StaleDataException("Attempted to access a cursor after it has been closed.");
        }
    }

    @Override
    public int getCount() {
        throwIfCursorIsClosed();
        return mCount;
    }

    @Override
    public boolean onMove(int oldPosition, int newPosition) {
        throwIfCursorIsClosed();

        try {
            // Make sure we have the proper window
            if (mWindow == null
                    || newPosition < mWindow.getStartPosition()
                    || newPosition >= mWindow.getStartPosition() + mWindow.getNumRows()) {
                setWindow(mBulkCursor.getWindow(newPosition));
            } else if (mWantsAllOnMoveCalls) {
                mBulkCursor.onMove(newPosition);
            }
        } catch (RemoteException ex) {
            // We tried to get a window and failed
            Log.e(TAG, "Unable to get window because the remote process is dead");
            return false;
        }

        // Couldn't obtain a window, something is wrong
        if (mWindow == null) {
            return false;
        }

        return true;
    }

    @Override
    public void deactivate() {
        // This will call onInvalidated(), so make sure to do it before calling release,
        // which is what actually makes the data set invalid.
        super.deactivate();

        if (mBulkCursor != null) {
            try {
                mBulkCursor.deactivate();
            } catch (RemoteException ex) {
                Log.w(TAG, "Remote process exception when deactivating");
            }
        }
    }
    
    @Override
    public void close() {
        super.close();

        if (mBulkCursor != null) {
            try {
                mBulkCursor.close();
            } catch (RemoteException ex) {
                Log.w(TAG, "Remote process exception when closing");
            } finally {
                mBulkCursor = null;
            }
        }
    }

    @Override
    public boolean requery() {
        throwIfCursorIsClosed();

        try {
            mCount = mBulkCursor.requery(getObserver());
            if (mCount != -1) {
                mPos = -1;
                setWindow(null);

                // super.requery() will call onChanged. Do it here instead of relying on the
                // observer from the far side so that observers can see a correct value for mCount
                // when responding to onChanged.
                super.requery();
                return true;
            } else {
                deactivate();
                return false;
            }
        } catch (Exception ex) {
            Log.e(TAG, "Unable to requery because the remote process exception " + ex.getMessage());
            deactivate();
            return false;
        }
    }

    @Override
    public String[] getColumnNames() {
        throwIfCursorIsClosed();

        return mColumns;
    }

    @Override
    public Bundle getExtras() {
        throwIfCursorIsClosed();

        try {
            return mBulkCursor.getExtras();
        } catch (RemoteException e) {
            // This should never happen because the system kills processes that are using remote
            // cursors when the provider process is killed.
            throw new RuntimeException(e);
        }
    }

    @Override
    public Bundle respond(Bundle extras) {
        throwIfCursorIsClosed();

        try {
            return mBulkCursor.respond(extras);
        } catch (RemoteException e) {
            // the system kills processes that are using remote cursors when the provider process
            // is killed, but this can still happen if this is being called from the system process,
            // so, better to log and return an empty bundle.
            Log.w(TAG, "respond() threw RemoteException, returning an empty bundle.", e);
            return Bundle.EMPTY;
        }
    }
}




Java Source Code List

aosp.android.database.BulkCursorDescriptor.java
aosp.android.database.BulkCursorNative.java
aosp.android.database.BulkCursorToCursorAdaptor.java
aosp.android.database.CrossProcessCursorWrapper.java
aosp.android.database.CursorToBulkCursorAdaptor.java
aosp.android.database.IBulkCursor.java
aosp.android.database.MoreDatabaseUtils.java
org.devtcg.sqliteserver.SQLiteContentProviderServer.java
org.devtcg.sqliteserver.SQLiteServerConnectionManager.java
org.devtcg.sqliteserver.SQLiteServerConnection.java
org.devtcg.sqliteserver.SQLiteServer.java
org.devtcg.sqliteserver.SQLiteServiceServer.java
org.devtcg.sqliteserver.exception.SQLiteServerException.java
org.devtcg.sqliteserver.impl.ExecutorHelper.java
org.devtcg.sqliteserver.impl.SQLiteExecutor.java
org.devtcg.sqliteserver.impl.ServerImplProvider.java
org.devtcg.sqliteserver.impl.binder.AbstractBinderClient.java
org.devtcg.sqliteserver.impl.binder.BinderHandle.java
org.devtcg.sqliteserver.impl.binder.BundleUtils.java
org.devtcg.sqliteserver.impl.binder.ClientTransactor.java
org.devtcg.sqliteserver.impl.binder.ContentObserverProxy.java
org.devtcg.sqliteserver.impl.binder.ContentProviderClient.java
org.devtcg.sqliteserver.impl.binder.SQLiteServerProtocolException.java
org.devtcg.sqliteserver.impl.binder.ServerImpl.java
org.devtcg.sqliteserver.impl.binder.ServerState.java
org.devtcg.sqliteserver.impl.binder.ServiceClient.java
org.devtcg.sqliteserver.impl.binder.ThreadAffinityExecutor.java
org.devtcg.sqliteserver.impl.binder.protocol.AbstractCommandHandler.java
org.devtcg.sqliteserver.impl.binder.protocol.AbstractCommandMessage.java
org.devtcg.sqliteserver.impl.binder.protocol.AcquireCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.BeginTransactionCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.DeleteCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.EndTransactionCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.ExceptionTransportHelper.java
org.devtcg.sqliteserver.impl.binder.protocol.ExecSQLCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.InsertCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.MethodName.java
org.devtcg.sqliteserver.impl.binder.protocol.RawQueryCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.ReleaseCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.SetTransactionSuccessfulCommand.java
org.devtcg.sqliteserver.impl.binder.protocol.UpdateCommand.java
org.devtcg.sqliteserver.sample.MyActivity.java
org.devtcg.sqliteserver.sample.MyOpenHelper.java
org.devtcg.sqliteserver.sample.TestContentProvider.java
org.devtcg.sqliteserver.sample.TestService.java