/* * 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.outrigger; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.rmi.MarshalledObject; import java.rmi.RemoteException; import net.jini.security.ProxyPreparer; /** * This class holds a proxy for some remote resource. When * persisted the proxy is marshalled in its own * {@link MarshalledObject} so this object can be unmarshalled * even if the proxy can't be (say because it codebase is * unavailable). The {@link #get} method can * be used to retrieve the proxy on demand. * * @author Sun Microsystems, Inc. * */ class StorableReference implements Externalizable { /** The proxy in marshalled form */ private MarshalledObject bytes; /** A cached copy of the unmarshalled proxy */ private transient Object obj; /** True if the <code>obj</code> has been prepared */ private transient boolean prepared; private static final boolean DEBUG = false; private static final long serialVersionUID = -3793675220968988873L; /** * Create a <code>StorableReference</code> that will hold * <code>obj</code>. */ public StorableReference(Object obj) { if (obj == null) throw new NullPointerException("obj cannot be null"); this.obj = obj; prepared = true; } /** Used by the object output stream. */ public StorableReference() { } /** * Return the proxy. If necessary deserialize the * proxy and optionally prepare it. Will only deserialize the * reference if it has not already been deserialized. Will * only prepare the object if <code>preparer</code> is non-null * and no previous call to get has succeeded. If this method * throws an exception, preparation has not succeeded. If a * previous call to this method has succeed, all future * calls will succeed and return the same object as the * first successful call. * * @param preparer the <code>ProxyPreparer</code> to * be used to prepare the reference. May * be <code>null</code>. * @return the remote reference contained in this object * @throws IOException if the unmarshalling fails. Will * also throw {@link RemoteException} * if <code>preparer.prepareProxy</code> * does. * @throws ClassNotFoundException if unmarshalling fails * with one. * @throws SecurityException if <code>preparer</code> does. */ public synchronized Object get(ProxyPreparer preparer) throws IOException, ClassNotFoundException { /* Even though we may be doing remote ops, it is * ok that we are synchronized. It does not * matter if a competing thread waits on this * lock, or waits doing the same remote operation * the owner of the lock is doing (in fact it * is better for the second thread to wait instead * of duplicating the work of the first). */ if (obj == null) obj = bytes.get(); if (!prepared) { if (preparer != null) obj = preparer.prepareProxy(obj); prepared = true; } return obj; } /** * @serialData */ // inherit doc comment public void writeExternal(ObjectOutput out) throws IOException { synchronized (this) { if (bytes == null) bytes = new MarshalledObject(obj); } out.writeObject(bytes); } // inherit doc comment public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { bytes = (MarshalledObject)in.readObject(); } }