io.v.android.impl.google.services.beam.VBeamServer.java Source code

Java tutorial

Introduction

Here is the source code for io.v.android.impl.google.services.beam.VBeamServer.java

Source

// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.android.impl.google.services.beam;

import android.util.Pair;

import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

import io.v.android.v23.VBeam;
import io.v.v23.context.VContext;
import io.v.v23.rpc.ServerCall;
import io.v.v23.verror.VException;

class VBeamServer implements IntentBeamerServer {
    private static final long EXPIRATION_MS = 60000;

    private final Map<String, Long> requestMap = new LinkedHashMap<>();
    private final VBeam.IntentCreator callback;

    public VBeamServer(VBeam.IntentCreator creator) throws VException {
        this.callback = creator;
    }

    @Override
    public synchronized ListenableFuture<GetIntentOut> getIntent(VContext ctx, ServerCall call, String secret) {
        evictStaleRequests();
        if (requestMap.remove(secret) != null) {
            try {
                return Futures.transform(callback.createIntent(ctx, call),
                        new AsyncFunction<Pair<String, byte[]>, GetIntentOut>() {

                            @Override
                            public ListenableFuture<GetIntentOut> apply(Pair<String, byte[]> input)
                                    throws Exception {
                                return convertIntent(input);
                            }
                        });
            } catch (Throwable t) {
                return Futures.immediateFailedFuture(t);
            }
        }
        return Futures.immediateFailedFuture(new VException("Bad request"));
    }

    private static ListenableFuture<GetIntentOut> convertIntent(Pair<String, byte[]> intent) {
        GetIntentOut out = new GetIntentOut();
        out.intentUri = intent.first;
        out.payload = intent.second;
        return Futures.immediateFuture(out);
    }

    private synchronized void evictStaleRequests() {
        long now = System.currentTimeMillis();
        for (Iterator<Long> it = requestMap.values().iterator(); it.hasNext();) {
            long l = it.next();
            if (l > now || l < now - EXPIRATION_MS) {
                it.remove();
            } else {
                // LinkedHashMap is sorted by insertion order, so oldest entry is first.
                break;
            }
        }
    }

    synchronized String newRequest() {
        evictStaleRequests();
        String secret = UUID.randomUUID().toString();
        requestMap.put(secret, System.currentTimeMillis());
        return secret;
    }
}