Package com.sun.jini.jeri.internal.runtime

Source Code of com.sun.jini.jeri.internal.runtime.DgcRequestDispatcher

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this 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
* 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.sun.jini.jeri.internal.runtime;

import com.sun.jini.jeri.internal.runtime.ObjectTable.NoSuchObject;
import com.sun.jini.logging.Levels;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.rmi.server.ExportException;
import java.rmi.server.Unreferenced;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jini.core.constraint.InvocationConstraints;
import net.jini.export.ServerContext;
import net.jini.id.Uuid;
import net.jini.id.UuidFactory;
import net.jini.io.MarshalInputStream;
import net.jini.io.UnsupportedConstraintException;
import net.jini.jeri.BasicInvocationDispatcher;
import net.jini.jeri.InboundRequest;
import net.jini.jeri.InvocationDispatcher;
import net.jini.jeri.RequestDispatcher;
import net.jini.jeri.ServerCapabilities;

/**
*
* @author peter
*/
public class DgcRequestDispatcher implements RequestDispatcher {
    private static final Logger logger =
  Logger.getLogger("net.jini.jeri.BasicJeriExporter");

    private static final Collection<Method> dgcDispatcherMethods =
            new ArrayList<Method>(2);
    static {
  Method[] methods = DgcServer.class.getMethods();
  for (int i = 0; i < methods.length; i++) {
      final Method m = methods[i];
      AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
        m.setAccessible(true);
        return null;
    }
      });
      dgcDispatcherMethods.add(m);
  }
    }

    private static final ServerCapabilities dgcServerCapabilities =
  new ServerCapabilities() {
      public InvocationConstraints checkConstraints(
    InvocationConstraints constraints)
    throws UnsupportedConstraintException
      {
    assert constraints.equals(InvocationConstraints.EMPTY);
    return InvocationConstraints.EMPTY;
      }
  };
       
    private final Unreferenced unrefCallback;
    private final ObjectTable table;
    private final ConcurrentMap<Uuid,Target> idTable =
            new ConcurrentHashMap<Uuid,Target>();
    private final AtomicInteger dgcEnabledCount =  new AtomicInteger()// guarded by idTable lock

    private final InvocationDispatcher dgcDispatcher;
    private final DgcServer dgcServer;

    DgcRequestDispatcher(Unreferenced unrefCallback, ObjectTable table ) {
        this.unrefCallback = unrefCallback;
        this.table = table;
        try {
            dgcDispatcher =
                new BasicInvocationDispatcher(
                    dgcDispatcherMethods, dgcServerCapabilities,
                    null, null, this.getClass().getClassLoader())
                {
                    protected ObjectInputStream createMarshalInputStream(
                        Object impl,
                        InboundRequest request,
                        boolean integrity,
                        Collection context)
                        throws IOException
                    {
                        ClassLoader loader = getClassLoader();
                        return new MarshalInputStream(
                            request.getRequestInputStream(),
                            loader, integrity, loader,
                            Collections.unmodifiableCollection(context));
                        // useStreamCodebases() not invoked
                    }
                };
        } catch (ExportException e) {
            throw new AssertionError();
        }
        this.dgcServer = table.getDgcServer(this);
    }

    boolean forTable(ObjectTable table) {
        return this.table == table;
    }

    boolean isReferenced() {
            return !idTable.isEmpty();
    }

    Target get(Uuid id) {
            return idTable.get(id);
    }

    void put(Target target) throws ExportException {
        Uuid id = target.getObjectIdentifier();
        if (id.equals(Jeri.DGC_ID)) {
            throw new ExportException(
                "object identifier reserved for DGC");
        }
        Target exists = idTable.putIfAbsent(id, target);
        if (exists != null){
            throw new ExportException(
                "object identifier already in use");
        }
        if (target.getEnableDGC()) {
            dgcEnabledCount.incrementAndGet();
        }
    }

    void remove(Target target, boolean gc) {
            Uuid id = target.getObjectIdentifier();
            boolean removed = idTable.remove(id, target);
            if (target.getEnableDGC() && removed) {
                int count = dgcEnabledCount.decrementAndGet();
                assert count >= 0;
            }

        if (gc && idTable.isEmpty()) {
            /*
             * We have to be careful to make this callback without holding
             * the lock for idTable, because the callback implementation
             * will likely be code that calls this object's isReferenced
             * method in its own synchronized block.
             *
             * This also means it is possible (although unlikely) for the
             * idtable to become non empty before making this call.
             */
            unrefCallback.unreferenced();
        }
    }

    private boolean hasDgcEnabledTargets() {
            return dgcEnabledCount.get() > 0;
    }

    public void dispatch(InboundRequest request) {
        try {
            InputStream in = request.getRequestInputStream();
            Uuid id = UuidFactory.read(in);
            Target target = null;
            if (logger.isLoggable(Level.FINEST)) {
                logger.log(Level.FINEST, "id={0}", id);
            }

            try {
                /*
                 * The DGC object identifier is hardwired here,
                 * rather than install it in idTable; this
                 * eliminates the need to worry about not counting
                 * the DGC server as an exported object in the
                 * table, and it doesn't need all of the machinery
                 * that Target provides.
                 */
                if (id.equals(Jeri.DGC_ID)) {
                    dispatchDgcRequest(request);
                    return;
                }

                target = get(id);
                if (target == null) {
                    logger.log(Level.FINEST, "id not in table");
                    throw new NoSuchObject();
                }
                target.dispatch(request);
            } catch (NoSuchObject e) {
                in.close();
                OutputStream out = request.getResponseOutputStream();
                out.write(Jeri.NO_SUCH_OBJECT);
                out.close();

                if (logger.isLoggable(Levels.FAILED)) {
                    logger.log(Levels.FAILED, "no such object: {0}", id);
                }
            }
        } catch (IOException e) {
            request.abort();

            if (logger.isLoggable(Levels.FAILED)) {
                logger.log(Levels.FAILED,
                           "I/O exception dispatching request", e);
            }
        }
    }

    private void dispatchDgcRequest(final InboundRequest request)
        throws IOException, NoSuchObject
    {
        if (!hasDgcEnabledTargets()) {
            logger.log(Level.FINEST, "no DGC-enabled targets");
            throw new NoSuchObject();
        }

        OutputStream out = request.getResponseOutputStream();
        out.write(Jeri.OBJECT_HERE);

        final Collection context = new ArrayList(5);
        request.populateContext(context);

        ServerContext.doWithServerContext(new Runnable() {
            public void run() {
                dgcDispatcher.dispatch(dgcServer, request, context);
            }
        }, Collections.unmodifiableCollection(context));

    }
}
TOP

Related Classes of com.sun.jini.jeri.internal.runtime.DgcRequestDispatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.