
com.caucho.v5.amp.vault.VaultDriverBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of baratine Show documentation
Show all versions of baratine Show documentation
A reactive Java web server.
/*
* Copyright (c) 1998-2015 Caucho Technology -- all rights reserved
*
* This file is part of Baratine(TM)
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Baratine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Baratine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Baratine; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Alex Rojkov
*/
package com.caucho.v5.amp.vault;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.caucho.v5.amp.ServiceRefAmp;
import com.caucho.v5.amp.ServicesAmp;
import com.caucho.v5.amp.message.HeadersNull;
import com.caucho.v5.amp.message.QueryWithResultMessage_N;
import com.caucho.v5.amp.spi.HeadersAmp;
import com.caucho.v5.amp.spi.OutboxAmp;
import com.caucho.v5.amp.stub.MethodAmp;
import com.caucho.v5.amp.stub.MethodAmpBase;
import com.caucho.v5.amp.stub.StubAmp;
import com.caucho.v5.amp.stub.TransferAsset;
import com.caucho.v5.config.ConfigException;
import com.caucho.v5.convert.bean.FieldBean;
import com.caucho.v5.convert.bean.FieldBeanFactory;
import com.caucho.v5.inject.type.TypeRef;
import com.caucho.v5.util.L10N;
import io.baratine.service.Result;
import io.baratine.vault.Id;
public class VaultDriverBase
implements VaultDriver
{
private static final L10N L = new L10N(VaultDriverBase.class);
private static final Logger log
= Logger.getLogger(VaultDriverBase.class.getName());
private ServicesAmp _ampManager;
private Class _idClass;
private Class _assetClass;
private String _address;
private Supplier _idGen;
private String _prefix;
private FieldBean _idField;
public VaultDriverBase(ServicesAmp ampManager,
Class assetClass,
Class idClass,
String address)
{
Objects.requireNonNull(ampManager);
Objects.requireNonNull(assetClass);
Objects.requireNonNull(idClass);
_ampManager = ampManager;
_assetClass = assetClass;
_idClass = idClass;
if (address == null) {
address = "/" + assetClass.getSimpleName();
}
_address = address;
_prefix = address + "/";
_idField = introspectId(assetClass);
if (_idField == null && ! Void.class.equals(idClass)) {
throw new VaultException(L.l("Missing @Id for asset '{0}'",
assetClass.getName()));
}
}
private FieldBean introspectId(Class> assetClass)
{
if (assetClass == null) {
return null;
}
for (Field field : assetClass.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (field.isAnnotationPresent(Id.class)) {
return FieldBeanFactory.get(field);
}
else if (field.getName().equals("id")) {
return FieldBeanFactory.get(field);
}
else if (field.getName().equals("_id")) {
return FieldBeanFactory.get(field);
}
}
return introspectId(assetClass.getSuperclass());
}
public String getAddress()
{
return _address;
}
@Override
public MethodVault newMethod(Method method)
{
if (! Modifier.isAbstract(method.getModifiers())) {
throw new IllegalStateException(String.valueOf(method));
}
else if (method.getName().startsWith("create")) {
Method target = entityMethod(method);
if (target != null) {
return newCreateMethod(target);
}
else {
return newCreateMethodDTO(method);
}
}
else {
return new MethodVaultNull<>(method.getName() + " " + getClass().getName());
}
}
@Override
public MethodVault newMethod(Class> type,
String methodName,
Class> []paramTypes)
{
Objects.requireNonNull(type);
MethodVault method = newMethodRec(type, methodName, paramTypes);
if (method != null) {
return method;
}
throw new IllegalStateException(L.l("Unknown method {0}.{1} {2}",
type.getSimpleName(),
methodName,
Arrays.asList(paramTypes)));
}
protected MethodVault newMethodRec(Class> type,
String methodName,
Class> []paramTypes)
{
if (type == null) {
return null;
}
for (Method method : type.getDeclaredMethods()) {
if (method.getName().equals(methodName)
&& Arrays.equals(MethodAmp.paramTypes(method),
paramTypes)) {
return newMethod(method);
}
}
MethodVault methodVault
= newMethodRec(type.getSuperclass(), methodName, paramTypes);
if (methodVault != null) {
return methodVault;
}
for (Class> typeIface : type.getInterfaces()) {
methodVault = newMethodRec(typeIface, methodName, paramTypes);
if (methodVault != null) {
return methodVault;
}
}
return null;
}
private MethodVault newCreateMethod(Method targetMethod)
{
Supplier idGen = idSupplier();
try {
//targetMethod.setAccessible(true);
//MethodHandle targetHandle = MethodHandles.lookup().unreflect(targetMethod);
return new MethodVaultCreate(_ampManager, idGen, targetMethod);
} catch (Exception e) {
e.printStackTrace();;
throw new IllegalStateException(e);
}
}
private MethodVault newCreateMethodDTO(Method vaultMethod)
{
Supplier idGen = idSupplier();
try {
Class> []params = vaultMethod.getParameterTypes();
if (params.length != 2) {
throw new ConfigException(L.l("'{0}' is an invalid vault create.",
vaultMethod));
}
TransferAsset transfer = new TransferAsset<>(_assetClass, params[0]);
TypeRef resultRef = TypeRef.of(vaultMethod.getGenericParameterTypes()[1]);
TypeRef valueRef = resultRef.to(Result.class).param(0);
MethodAmp methodAmp;
if (valueRef.rawClass().equals(_idField.field().getType())) {
methodAmp = new MethodAmpCreateDTO<>(transfer, _idField);
}
else {
methodAmp = new MethodAmpCreateDTO<>(transfer, null);
}
return new MethodVaultCreateDTO(_ampManager, idGen,
vaultMethod,
methodAmp);
} catch (Exception e) {
e.printStackTrace();;
throw new IllegalStateException(e);
}
}
private Supplier idSupplier()
{
synchronized (this) {
if (_idGen == null) {
_idGen = VaultIdGenerator.create(_idClass);
}
return _idGen;
}
}
private Method entityMethod(Method source)
{
try {
return _assetClass.getMethod(source.getName(), source.getParameterTypes());
} catch (Exception e) {
log.log(Level.FINER, e.toString(), e);
return null;
}
}
@Override
public String toString()
{
return getClass().getSimpleName()
+ "["
+ _assetClass
+ "]";
}
private static class MethodVaultNull implements MethodVault
{
private String _methodName;
private RuntimeException _sourceExn;
MethodVaultNull(String methodName)
{
_methodName = methodName;
_sourceExn = new UnsupportedOperationException(_methodName);
_sourceExn.fillInStackTrace();
}
@Override
public void invoke(Result result, Object[] args)
{
throw new UnsupportedOperationException(_sourceExn);
}
}
private class MethodVaultCreate implements MethodVault
{
private ServicesAmp _ampManager;
private Supplier _idGen;
private String _methodName;
private MethodAmp _method;
private Class>[] _paramTypes;
MethodVaultCreate(ServicesAmp ampManager,
Supplier idGen,
Method method)
{
Objects.requireNonNull(ampManager);
Objects.requireNonNull(idGen);
Objects.requireNonNull(method);
_ampManager = ampManager;
_idGen = idGen;
_methodName = method.getName();
_paramTypes = MethodAmp.paramTypes(method);
}
private MethodAmp method(ServiceRefAmp childRef)
{
if (_method == null) {
// XXX:
Class> returnType = void.class;
_method = childRef.method(_methodName, returnType, _paramTypes).method();
}
return _method;
}
@Override
public void invoke(Result result, Object[] args)
{
String id = _idGen.get();
ServiceRefAmp childRef = _ampManager.service(_prefix + id);
long timeout = 10000L;
try (OutboxAmp outbox = OutboxAmp.currentOrCreate(_ampManager)) {
HeadersAmp headers = HeadersNull.NULL;
QueryWithResultMessage_N msg
= new QueryWithResultMessage_N<>(outbox,
headers,
result,
timeout,
childRef,
method(childRef),
args);
msg.offer(timeout);
}
}
}
private class MethodVaultCreateDTO implements MethodVault
{
private ServicesAmp _ampManager;
private Supplier _idGen;
//private String _methodName;
private MethodAmp _method;
MethodVaultCreateDTO(ServicesAmp ampManager,
Supplier idGen,
Method method,
MethodAmp methodAmp)
{
Objects.requireNonNull(ampManager);
Objects.requireNonNull(idGen);
Objects.requireNonNull(method);
Objects.requireNonNull(method);
_ampManager = ampManager;
_idGen = idGen;
//_methodName = methodName;
_method = methodAmp;
}
@Override
public void invoke(Result result, Object[] args)
{
String id = _idGen.get();
ServiceRefAmp childRef = _ampManager.service(_prefix + id);
long timeout = 10000L;
try (OutboxAmp outbox = OutboxAmp.currentOrCreate(_ampManager)) {
HeadersAmp headers = HeadersNull.NULL;
QueryWithResultMessage_N msg
= new QueryWithResultMessage_N<>(outbox,
headers,
result,
timeout,
childRef,
_method,
args);
msg.offer(timeout);
}
}
}
private class MethodAmpCreateDTO extends MethodAmpBase
{
private TransferAsset _transfer;
private FieldBean _idField;
MethodAmpCreateDTO(TransferAsset transfer,
FieldBean idField)
{
Objects.requireNonNull(transfer);
_transfer = transfer;
_idField = idField;
}
@Override
public void query(HeadersAmp headers,
Result> result,
StubAmp stub,
Object []args)
{
T asset = (T) stub.bean();
S transfer = (S) args[0];
Objects.requireNonNull(asset);
Objects.requireNonNull(transfer);
_transfer.toAsset(asset, transfer);
stub.onModify();
if (_idField != null) {
((Result) result).ok(_idField.getObject(asset));
}
else {
result.ok(null);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy