blob: e561c9b001f9daf190bc618cc0fd2e308648ba03 [file] [log] [blame]
// Copyright (C) 2008 The Android Open Source Project
//
// 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 com.google.gerrit.httpd.rpc;
import com.google.gerrit.common.errors.InvalidQueryException;
import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.inject.Provider;
import java.io.IOException;
/** Support for services which require a {@link ReviewDb} instance. */
public class BaseServiceImplementation {
private final Provider<ReviewDb> schema;
private final Provider<? extends CurrentUser> currentUser;
protected BaseServiceImplementation(
final Provider<ReviewDb> schema, final Provider<? extends CurrentUser> currentUser) {
this.schema = schema;
this.currentUser = currentUser;
}
protected Account.Id getAccountId() {
CurrentUser u = currentUser.get();
return u.isIdentifiedUser() ? u.getAccountId() : null;
}
protected CurrentUser getUser() {
return currentUser.get();
}
protected ReviewDb getDb() {
return schema.get();
}
/**
* Executes {@code action.run} with an active ReviewDb connection.
*
* <p>A database handle is automatically opened and closed around the action's {@link
* Action#run(ReviewDb)} method. OrmExceptions are caught and passed into the onFailure method of
* the callback.
*
* @param <T> type of result the callback expects.
* @param callback the callback that will receive the result.
* @param action the action logic to perform.
*/
protected <T> void run(final AsyncCallback<T> callback, final Action<T> action) {
try {
final T r = action.run(schema.get());
if (r != null) {
callback.onSuccess(r);
}
} catch (InvalidQueryException e) {
callback.onFailure(e);
} catch (NoSuchProjectException e) {
if (e.getMessage() != null) {
callback.onFailure(new NoSuchEntityException(e.getMessage()));
} else {
callback.onFailure(new NoSuchEntityException());
}
} catch (NoSuchGroupException e) {
callback.onFailure(new NoSuchEntityException());
} catch (OrmRuntimeException e) {
Exception ex = e;
if (e.getCause() instanceof OrmException) {
ex = (OrmException) e.getCause();
}
handleOrmException(callback, ex);
} catch (OrmException e) {
handleOrmException(callback, e);
} catch (IOException e) {
callback.onFailure(e);
} catch (Failure e) {
if (e.getCause() instanceof NoSuchProjectException
|| e.getCause() instanceof NoSuchChangeException) {
callback.onFailure(new NoSuchEntityException());
} else {
callback.onFailure(e.getCause());
}
}
}
private static <T> void handleOrmException(final AsyncCallback<T> callback, Exception e) {
if (e.getCause() instanceof Failure) {
callback.onFailure(e.getCause().getCause());
} else if (e.getCause() instanceof NoSuchEntityException) {
callback.onFailure(e.getCause());
} else {
callback.onFailure(e);
}
}
/** Exception whose cause is passed into onFailure. */
public static class Failure extends Exception {
private static final long serialVersionUID = 1L;
public Failure(final Throwable why) {
super(why);
}
}
/** Arbitrary action to run with a database connection. */
public interface Action<T> {
/**
* Perform this action, returning the onSuccess value.
*
* @param db an open database handle to be used by this connection.
* @return he value to pass to {@link AsyncCallback#onSuccess(Object)}.
* @throws OrmException any schema based action failed.
* @throws Failure cause is given to {@link AsyncCallback#onFailure(Throwable)}.
* @throws NoSuchProjectException
* @throws NoSuchGroupException
* @throws InvalidQueryException
*/
T run(ReviewDb db)
throws OrmException, Failure, NoSuchProjectException, NoSuchGroupException,
InvalidQueryException, IOException;
}
}