📄 genericpeergroup.java
字号:
* Ask a group to unregister and unload a service
* @param service handle to the service to be removed
*/
protected void removeService (ModuleClassID name, Service service)
throws ServiceNotFoundException, ViolationException
{
removeServiceSync(name, service);
clearShortCut(name);
// service.finalize(); FIXME. We probably need a terminate()
// method instead.
// FIXME: [jice@jxta.org 20011013] to make sure the service is
// no-longer referenced, we should always return interfaces, and
// have a way to cut the reference to the real service in the
// interfaces. One way of doing that would be to have to levels
// of indirection: we should keep one and return references to it.
// when we want to cut the service loose, we should clear the
// reference from the interface that we own before letting it go.
// We need to study the consequences of doing that before implementing
// it.
}
/**
* Evaluates if the given compatibility statement makes the module that
* bears it is lodable by this group.
*
* @return boolean True if the given statement is compatible.
*/
abstract public boolean compatible(Element compat);
/**
* Load a module from a ModuleImplAdv.
* Compatibility is checked and load is attempted. If compatible and loaded
* successfuly, the resulting Module is init()ed and returned.
*/
public Module loadModule(ID assigned,
Advertisement impl)
throws ProtocolNotSupportedException, PeerGroupException {
// The following may trigger a class cast exception
// That's a normal part of the process; DiscoveryService
// may return various types of ADVS that match our
// queries.
ModuleImplAdvertisement implAdv = (ModuleImplAdvertisement) impl;
Element compat = implAdv.getCompat();
if (! compatible(compat)) {
throw new ProtocolNotSupportedException("Incompatible Module");
}
Module newMod;
try {
// Good one. Try it.
newMod = (Module) loader.loadClass(implAdv.getCode(),
implAdv.getUri(),
true).newInstance();
} catch (Exception loaderWhines) {
// Simplify loader generated exceptions; there's just too many.
throw new PeerGroupException(loaderWhines.getMessage());
}
newMod.init(this, assigned, implAdv);
if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug("Loaded. class : " + implAdv.getCode());
// Publish or renew the lease of this adv since we're using it.
try {
if (discovery != null) discovery.publish(impl,
DiscoveryService.ADV,
DEFAULT_LIFETIME,
DEFAULT_EXPIRATION);
} catch (Exception notCritical) {
}
// If we reached this point we're done.
return newMod;
}
/**
* Load a module from a spec id.
* Advertisement is sought, compatibility is checked on all candidates
* and load is attempted. The first one that is compatible and loads
* successfuly is init()ed and returned.
*/
public Module loadModule(ID assigned, ModuleSpecID specID, int where) {
boolean here = (where == Here || where == Both);
boolean fromParent = (where == FromParent || where == Both);
if (here) {
if (discovery != null) {
// Disco does not have quite enough capabilities to make
// this efficient, but we'll make do.
Enumeration all =
discoverSome(DiscoveryService.ADV,
"MSID",
specID.toString(),
120,
ModuleImplAdvertisement.class);
while (all.hasMoreElements()) {
try {
Advertisement found =
(Advertisement) all.nextElement();
// Here's one.
// First check that the MSID is realy the one we're
// looking for. It could have appeared somewhere else
// in the adv than where we're looking, and discovery
// doesn't know the difference.
if (! ((ModuleImplAdvertisement) found).getModuleSpecID().equals(specID)) {
continue;
}
// Try it. If "found" is not useable it will
// trigger an exception and we'll try the next.
Module newMod = loadModule(assigned, found);
// If we reach that point, the module is good.
return newMod;
} catch(Exception e) {
if (LOG.isEnabledFor(Priority.INFO)) LOG.info("Not a valid impl adv: ", e);
}
}
}
}
if (fromParent) {
if (parentGroup == null) {
// Could have dedicated CM folder for bootstrap.
// Fail for now. We can make do without it by
// allowing service impl advs to be in-lined.
if (LOG.isEnabledFor(Priority.WARN)) LOG.warn("Loading module from SpecID without discovery"
+ " is not yet supported.");
return null;
}
// Disco does not have quite enough capabilities to make
// this efficient yet, but we'll make do.
Enumeration all =
discoverSome(parentGroup.getDiscoveryService(),
DiscoveryService.ADV,
"MSID",
specID.toString(),
120,
ModuleImplAdvertisement.class);
while (all.hasMoreElements()) {
try {
Advertisement found =
(Advertisement) all.nextElement();
// Here's one.
// First check that the MSID is realy the one we're
// looking for. It could have appeared somewhere else
// in the adv than where we're looking, and discovery
// doesn't know the difference.
if (! ((ModuleImplAdvertisement) found).getModuleSpecID().equals(specID)) {
continue;
}
// Try it. If "found" is not useable it will
// trigger an exception and we'll try the next.
Module newMod = loadModule(assigned, found);
// Renew the lease on this adv in the parent
// since we're using it.
try {
parentGroup.getDiscoveryService().publish(
found,
DiscoveryService.ADV,
DEFAULT_LIFETIME,
DEFAULT_EXPIRATION);
} catch (Exception notCritical) {
}
// If we reach that point, the module is good.
return newMod;
} catch(Exception e) {
if (LOG.isEnabledFor(Priority.WARN)) LOG.warn("Bad impl adv: ", e);
}
}
}
return null;
}
/*
* Now comes the API known only to RefPeerGroup.
* At the very least, all services have access to it.
* Not sure about applications yet.
*/
/**
* Get this group's parent group.
*/
public RefPeerGroup getParentGroup() {
return parentGroup;
}
/**
* Returns the config advertisment for this peer.
*
* @return Advertisement the advertisement.
*
* @since JXTA 1.0
*/
public Advertisement getConfigAdvertisement() {
// FIXME: [jice@jxta.org 20011022] Clone it for now. It would be way
// better if we had an immutable version to give away.
if (configAdvertisement == null) return null;
return (Advertisement) configAdvertisement.clone();
}
/**
* Sets the config advertisment for this peer. This one is restricted
* to subclasses and is for initialization only.
*
* @param config the advertisement.
*
* @since JXTA 1.0
*/
protected void setConfigAdvertisement(Advertisement config) {
configAdvertisement = (PeerAdvertisement) config;
}
/*
* Now comes the implementation of the public API, including the
* API mandated by the Service interface.
*/
/*
* Some minimal init.
* It is not done at Ctor time because the information might not be
* available then.
* We have to assume that we got a RefPeerGroup for parent. That's
* a rule of the implementation that is not visible to Applications:
* ANY GROUP IN THE REF IMPLEM IS A REFPEERGROUP.
*/
public void init(PeerGroup homeGroup, ID assignedID, Advertisement impl)
throws PeerGroupException {
this.implAdvertisement = (ModuleImplAdvertisement) impl;
this.parentGroup = (RefPeerGroup) homeGroup;
// Start building our peer adv.
peerAdvertisement = new PeerAdv();
// Do our part of the PeerAdv construction.
if (configAdvertisement != null) {
// Copy the group params to the peer adv.
// For now, all of them. There's only the root certificate.
peerAdvertisement.putServiceParam(
PeerGroup.peerGroupClassID,
configAdvertisement.getServiceParam(PeerGroup.peerGroupClassID));
// Normaly there will be a peer ID and a peer name in the
// config.
peerAdvertisement.setPeerID(configAdvertisement.getPeerID());
peerAdvertisement.setName(configAdvertisement.getName());
}
// Sort-out our groupID and group adv and apply a few sanity rules.
// update the adv accordingly.
// Depends if we're the platform or not (have a home group or not).
try {
String sGID;
PeerGroupID myGID;
// If we did not get a valid GID, fine, make one up.
// We are creating a whole new group.
if (assignedID == null || assignedID.equals(ID.nullID)) {
myGID = IDFactory.newPeerGroupID();
sGID = myGID.toString();
} else {
sGID = assignedID.toString();
myGID = (PeerGroupID) IDFactory.fromURL( new URL(sGID) );
}
// Now that we know our group id, update the peerAdvertisement too.
peerAdvertisement.setPeerGroupID(myGID);
if (homeGroup == null) {
// If we did not get a valid peer id, we'll initiate it here.
if (peerAdvertisement.getPeerID() == null
|| peerAdvertisement.getPeerID().equals(ID.nullID)) {
peerAdvertisement.setPeerID(IDFactory.newPeerID(myGID));
}
// If we did not get a valid peer name, make one up.
if (peerAdvertisement.getName() == null) {
peerAdvertisement.setName("Anonymous Coward");
}
} else {
// We're not the platform, which is the
// authoritative source of these values.
peerAdvertisement.setPeerID(homeGroup.getPeerID());
peerAdvertisement.setName(homeGroup.getPeerName());
if (assignedID != null
&& ! assignedID.equals(ID.nullID)) {
// Since we had a valid ID,
// see if we can find our own grp adv published in our
// parent (if any). Logic says if it exists it is already
// local. Otherwise, where did we get the SpecID that was
// used to get this implementation that we're executing
// just now ?
DiscoveryService disco = parentGroup.getDiscoveryService();
Enumeration found =
disco.getLocalAdvertisements(DiscoveryService.GROUP,
"GID",
sGID);
if (found.hasMoreElements()) {
peerGroupAdvertisement =
(PeerGroupAdvertisement) found.nextElement();
}
}
}
if (peerGroupAdvertisement == null) {
// No existing gadv. OK then we're creating the group or we're
// the platform, it seems. Start a grp adv with the essentials
// that we know.
peerGroupAdvertisement = new PeerGroupAdv();
peerGroupAdvertisement.setName("Anonymous Group");
peerGroupAdvertisement.setDescription("Nondescript Group");
peerGroupAdvertisement.setPeerGroupID(myGID);
peerGroupAdvertisement.setModuleSpecID(
implAdvertisement.getModuleSpecID());
} else {
published = true;
}
} catch(Exception any) {
if (LOG.isEnabledFor(Priority.DEBUG)) LOG.debug("Group init failed.", any);
throw new PeerGroupException(any.getMessage());
}
/*
* The rest of construction and initialization are left to the
* group subclass.
* That should include instanciating and setting the endpoint, and
* finally supplying it with endpoint protocols.
* That also includes instanciating the appropriate services
* and registering them.
* For an example, see the StdPeerGroup class.
*/
}
/**
* Start the peergroup.
* In practice, it means starting its main application. But that's for
* subclasses. GenericPeerGroup does not implement the concept of
* initial app anylonger. See subclasses.
*
* @return int Status.
*/
public int startApp(String[] arg) {
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -