Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* ============================================================================
*
* File: Actor.java
*----------------------------------------------------------------------------
*
* Copyright 2008 Erlend Nossum
*
* Licensed 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.
*
* Description: See javadoc below
*
* Created: Jul 19, 2008
* ============================================================================
*/
package org.semispace.actor;
import org.semispace.NameValueQuery;
import org.semispace.SemiEventRegistration;
import org.semispace.SemiLease;
import org.semispace.SemiSpace;
import org.semispace.SemiSpaceInterface;
import org.semispace.exception.ActorException;
import org.semispace.exception.SemiSpaceUsageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* Implementation of an actor. You need to register the actor in a space, in
* order to get a lifetime of the actor. The read and take templates are
* registered at this time as well.
*
*/
public abstract class Actor {
private static final Logger log = LoggerFactory.getLogger(Actor.class);
/**
* 10 years is "actorLifeMs" in this context
*/
private static final long FOREVER = SemiSpace.ONE_DAY*365*10;
private final Listnotifications = new ArrayList();
private SemiSpaceInterface space;
private Long actorId;
private long defaultLifeMsOfSpaceObject = 1000;
public long getDefaultLifeMsOfSpaceObject() {
return defaultLifeMsOfSpaceObject;
}
/**
* How long a message will live in the space when it is sent.
*/
public void setDefaultLifeMsOfSpaceObject(long defaultLifeMsOfSpaceObject) {
this.defaultLifeMsOfSpaceObject = defaultLifeMsOfSpaceObject;
}
/**
* Register with the space with a very long long actor life.
* Useful when you are actively using unregister, or expect
* the actor to live longer than the VM itself.
* @see Actor#unregister()
* @see Actor#register(SemiSpaceInterface, long)
*/
public final void register( SemiSpaceInterface registerWith ) {
register( registerWith, FOREVER );
}
/**
* You must register with a space in order to activate the
* actor.
* @param actorLifeMs How long the actor shall be active in milliseconds
* @see Actor#unregister()
*/
public final void register( SemiSpaceInterface registerWith, long actorLifeMs ) {
space = registerWith;
// Create id
NameValueQuery nvq = new NameValueQuery();
nvq.name = "internal";
nvq.value = "disregard";
SemiLease lease = space.write(nvq, 50);
actorId = Long.valueOf(lease.getHolderId());
lease.cancel();
ActorNotification an = null;
// Listen for elements to, eh, listen to
for ( Object toTake: getTakeTemplates() ) {
an = new ActorNotification( this, space, toTake, true );
SemiEventRegistration registration = space.notify(toTake, an, actorLifeMs);
if ( registration == null ) {
throw new ActorException("Did not manage to register with space.");
}
notifications.add( registration );
}
for ( Object toRead: getReadTemplates() ) {
an = new ActorNotification( this, space, toRead, false );
SemiEventRegistration registration = space.notify(toRead, an, actorLifeMs);
if ( registration == null ) {
throw new ActorException("Did not manage to register with space.");
}
notifications.add( registration );
}
// Listen for messages to myself of any kind
ActorMessage template = new ActorMessage();
template.setAddress(actorId);
an = new ActorNotification( this, space, template, true );
notifications.add( space.notify(template, an, actorLifeMs));
log.debug("Registered actor ("+getClass().getName()+") with id "+actorId+" and this object registered "+notifications.size()+" notification element(s).");
}
/**
* Removing the connection(s) from the space rendering the actor, for all
* practical purposes, dead.
*/
public void unregister() {
for (SemiEventRegistration registration : notifications ) {
registration.getLease().cancel();
}
notifications.clear();
space = null;
actorId = null;
}
/**
* Send two message to the space. The first is the object
* to write, the other is the manifest for the message, which can
* be used by the listening actor to find the originator.
* This method is intended only to be used when initiating an
* actor dialog, as the destination is unknown
*/
public void send( Object obj ) {
if ( actorId == null ) {
throw new SemiSpaceUsageException("Actor id must be set. Did you remember to register actor class?");
}
SemiLease lease = space.write(obj, defaultLifeMsOfSpaceObject);
ActorManifest manifest = new ActorManifest(Long.valueOf( lease.getHolderId()), actorId);
space.write(manifest, defaultLifeMsOfSpaceObject);
log.debug("Wrote manifest with holder id "+manifest.getHolderId());
//log.debug("send actor message containing: "+new XStream().toXML(msg));
}
/**
* This is the regular method for sending a message to an
* actor. The message will be delivered directly to the indicated actor.
* No of the parameters may be null.
* @param destinationId When replying to a message, the originatorId should
* be the destination id. i.e. the destination address
*/
public void send(Long destinationId, Object payload) {
if ( payload == null ) {
throw new SemiSpaceUsageException("No parameter is allowed to be null, but payload was. Destination id was "+destinationId);
}
if ( destinationId == null ) {
throw new SemiSpaceUsageException("No parameter is allowed to be null, but destination was. Are you certain that " +
"you used originatorId when replying? Payload class: "+payload.getClass().getName());
}
ActorMessage msg = new ActorMessage();
msg.setOriginatorId(actorId);
msg.setAddress( destinationId);
msg.setPayload(payload);
space.write(msg, defaultLifeMsOfSpaceObject);
}
/**
* @return Id of this actor provided that it is registered in a space.
*/
public Long getActorId() {
return actorId;
}
/**
* Default implementation which renders an empty array, ie nothing is
* tried taken. Exchange with relevant elements.
* Object are tried taken from the space. Observe that
* the object taken is the one that fits the template, and not
* necessarily the one which triggered the event.
*/
public Object[] getTakeTemplates() {
return new Object[0];
}
/**
* Default implementation which renders empty array, ie nothing is tried read.
* @see #getTakeTemplates()
*/
public Object[] getReadTemplates() {
return new Object[0];
}
/**
* Receive a message which either matches the template, or that is addressed to
* this actor in particular (which implies that you need to check the type
* for each message).
*/
public abstract void receive(ActorMessage msg);
}