All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.river.reggie.proxy.Item Maven / Gradle / Ivy

/*
 * 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 org.apache.river.reggie.proxy;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.lang.reflect.Proxy;
import java.rmi.MarshalException;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.RemoteObject;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jini.core.constraint.MethodConstraints;
import net.jini.core.constraint.RemoteMethodControl;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceItem;
import net.jini.security.Security;
import org.apache.river.action.GetBooleanAction;
import org.apache.river.api.io.AtomicSerial;
import org.apache.river.api.io.AtomicSerial.GetArg;
import org.apache.river.api.io.Valid;
import org.apache.river.logging.Levels;
import org.apache.river.proxy.MarshalledWrapper;
import org.apache.river.proxy.Bootstrap;

/**
 * An Item contains the fields of a ServiceItem packaged up for
 * transmission between client-side proxies and the registrar server.
 * Instances are never visible to clients, they are private to the
 * communication between the proxies and the server.
 * 

* This class only has a bare minimum of methods, to minimize * the amount of code downloaded into clients. * * @author Sun Microsystems, Inc. * */ @AtomicSerial public final class Item implements Serializable, Cloneable { private static final long serialVersionUID = 2L; private static final ObjectStreamField[] serialPersistentFields = { /** @serialField ServiceItem.serviceID. */ new ObjectStreamField("serviceID", ServiceID.class), /** @serialField The Class of ServiceItem.service converted to ServiceType. */ new ObjectStreamField("serviceType", ServiceType.class), /** @serialField The codebase of the service object. */ new ObjectStreamField("codebase", String.class), /** @serialField ServiceItem.service as a MarshalledWrapper. */ new ObjectStreamField("service", MarshalledWrapper.class), /** @serialField ServiceItem.attributeSets converted to EntryReps. */ new ObjectStreamField("attributeSets", EntryRep[].class), /** @serialField ServiceItem.attributeSets converted to EntryReps. */ new ObjectStreamField("bootstrapProxy", Proxy.class) }; /** Logger for Reggie. */ private static final Logger logger = Logger.getLogger("org.apache.river.reggie"); /** * Flag to enable JRMP impl-to-stub replacement during marshalling of * service proxy. */ private static final boolean enableImplToStubReplacement; static { Boolean b; try { b = (Boolean) Security.doPrivileged(new GetBooleanAction( "org.apache.river.reggie.enableImplToStubReplacement")); } catch (SecurityException e) { logger.log(Levels.HANDLED, "failed to read system property", e); b = Boolean.FALSE; } enableImplToStubReplacement = b.booleanValue(); } /** * ServiceItem.serviceID. * * @serial */ private ServiceID serviceID; // mutated by RegistrarImpl /** * The Class of ServiceItem.service converted to ServiceType. * * @serial */ public final ServiceType serviceType; /** * The codebase of the service object. * * @serial */ public final String codebase; /** * ServiceItem.service as a MarshalledWrapper. * * @serial */ public final MarshalledWrapper service; /** * ServiceItem.attributeSets converted to EntryReps. * * @serial */ private EntryRep[] attributeSets; // mutated by RegistrarImpl /** * Bootstrap proxy for registrar default method. * @serial */ Proxy bootstrapProxy; /** * Checks all invariants are satisfied during de-serialization. * @param arg * @return * @throws IOException * @throws ClassCastException * @throws NullPointerException */ private static boolean check(GetArg arg) throws IOException, ClassNotFoundException{ arg.get("serviceID", null, ServiceID.class); // serviceID is assigned by Reggie if null. arg.get("serviceType", null, ServiceType.class); // serviceType allowed to be null arg.get("codebase", null, String.class); // codebase allowed to be null Valid.notNull( arg.get("service", null, MarshalledWrapper.class), "service cannot be null"); // attributeSets can be null and can contain null arg.get("attributeSets", null, EntryRep[].class); Proxy bootstrapProxy = arg.get("bootstrapProxy", null, Proxy.class); if (bootstrapProxy != null) { if (Proxy.isProxyClass(bootstrapProxy.getClass())) return true; } return true; } /** * Failure is atomic, if any invariants aren't satisfied, construction fails * before an instance can be created. * @param arg * @throws IOException */ public Item(GetArg arg) throws IOException, ClassNotFoundException{ this(arg, check(arg)); }; private Item(GetArg arg, boolean check) throws IOException, ClassNotFoundException{ super(); // instance has been created here. serviceID = arg.get("serviceID", null, ServiceID.class); serviceType = arg.get("serviceType", null, ServiceType.class); codebase = arg.get("codebase", null, String.class); service = arg.get("service", null, MarshalledWrapper.class); attributeSets = Valid.copy(arg.get("attributeSets", null, EntryRep[].class)); bootstrapProxy = arg.get("bootstrapProxy", null, Proxy.class); } public Item(Item item, MethodConstraints constraints){ this(item.serviceID, item.serviceType, item.codebase, item.service, item.attributeSets.clone(), item.bootstrapProxy != null ? (Proxy)((RemoteMethodControl)item.bootstrapProxy).setConstraints(constraints): null ); } /** * Converts a ServiceItem to an Item. Any exception that results * is bundled up into a MarshalException. */ public Item(ServiceItem item) throws RemoteException { Object svc = item.service; if (enableImplToStubReplacement && svc instanceof Remote) { try { svc = RemoteObject.toStub((Remote) svc); if (logger.isLoggable(Level.FINER)) { logger.log(Level.FINER, "replacing {0} with {1}", new Object[]{ item.service, svc }); } } catch (NoSuchObjectException e) { } } // Now we need to create the bootstrap proxy for the new lookup method. bootstrapProxy = Bootstrap.create(svc); serviceID = item.serviceID; ServiceTypeBase stb = ClassMapper.toServiceTypeBase(svc.getClass()); serviceType = stb.type; codebase = stb.codebase; try { service = new MarshalledWrapper(svc); } catch (IOException e) { throw new MarshalException("error marshalling arguments", e); } attributeSets = EntryRep.toEntryRep(item.attributeSets, true); } public Item(ServiceID serviceID, ServiceType serviceType, String codebase, MarshalledWrapper service, EntryRep[] attrSets, Proxy bootstrap) { this.serviceID = serviceID; this.serviceType = serviceType; this.codebase = codebase; this.service = service; attributeSets = attrSets != null ? attrSets.clone() : new EntryRep[0]; this.bootstrapProxy = bootstrap; } /** * Convert back to a ServiceItem. If the service object cannot be * constructed, it is set to null. If an Entry cannot be constructed, * it is set to null. If a field of an Entry cannot be unmarshalled, * it is set to null. */ public ServiceItem get() { Object obj = null; try { obj = service.get(); } catch (Throwable e) { RegistrarProxy.handleException(e); } synchronized (this){ return new ServiceItem(serviceID, obj, EntryRep.toEntry(attributeSets)); } } public ServiceItem get(Collection context){ Object obj = null; try { obj = service.get(null, null, context); } catch (Throwable e) { RegistrarProxy.handleException(e); } synchronized (this){ return new ServiceItem(serviceID, obj, EntryRep.toEntry(attributeSets)); } } public Proxy getProxy() { return bootstrapProxy; } /** * Deep clone. This is really only needed in the server, * but it's very convenient to have here. */ @Override public Object clone() { EntryRep[] attrSets = (EntryRep[])attributeSets.clone(); for (int i = attrSets.length; --i >= 0; ) { attrSets[i] = (EntryRep)attrSets[i].clone(); } return new Item(serviceID, serviceType, codebase, service, attrSets, bootstrapProxy); } /** * Converts an ArrayList of Item to an array of ServiceItem. */ public static ServiceItem[] toServiceItem(List reps) { ServiceItem[] items = null; if (reps != null) { items = new ServiceItem[reps.size()]; for (int i = items.length; --i >= 0; ) { items[i] = ((Item)reps.get(i)).get(); } } return items; } private synchronized void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } /** * @return the serviceID */ public synchronized ServiceID getServiceID() { return serviceID; } /** * @param serviceID the serviceID to set */ public synchronized void setServiceID(ServiceID serviceID) { this.serviceID = serviceID; } /** * @return the attributeSets */ public synchronized EntryRep[] getAttributeSets() { return attributeSets == null ? null : attributeSets.clone(); } public synchronized EntryRep getAttributeSetAtIndex(int i){ return attributeSets == null ? null : attributeSets[i]; } public synchronized int getAttributeSetsLength(){ return attributeSets == null ? 0 : attributeSets.length; } /** * @param attributeSets the attributeSets to set */ public synchronized void setAttributeSets(EntryRep[] attributeSets) { this.attributeSets = attributeSets; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy