You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by rj...@apache.org on 2009/06/09 14:00:32 UTC
svn commit: r782968 [6/7] - in /directory/sandbox/slp: ./
src/main/java/org/apache/directory/slp/
src/main/java/org/apache/directory/slp/codec/
src/main/java/org/apache/directory/slp/extensions/
src/main/java/org/apache/directory/slp/impl/ src/main/jav...
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/ThreadedReplyFuture.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/ThreadedReplyFuture.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/ThreadedReplyFuture.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/ThreadedReplyFuture.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,301 @@
+/*
+ * 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.directory.slp.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.slp.ReplyFuture;
+import org.apache.directory.slp.messages.AbstractSLPReplyMessage;
+
+/**
+ * The future returned when performing SLP lookups. It can be accessed while results still come in using next(),
+ * or after all results have arrived using getResult().
+ *
+ * @author Lorenz Breu
+ *
+ */
+public class ThreadedReplyFuture implements ReplyFuture {
+
+ // used to wait for done status
+ protected final Object donelock = new Object();
+
+ //List of responses (i.e. message results)
+ protected final List<String> responses = new ArrayList<String>();
+
+ // List of responders, used to build initial list of previous responders for multicast convergence
+ protected final List<String> responders = new ArrayList<String>();
+
+ // point when reply future is closed automatically
+ protected long timeout;
+
+ // set to true when all operations producing results have completed
+ protected boolean done = false;
+
+ // the next position to be returned using the next() method.
+ // currently a future object is read by only one consumer.
+ private int nextPosition = 0;
+
+ // the list of scopes this future has to cover, used to control correct closure.
+ private List<String> unhandledScopes = new ArrayList<String>();
+
+ // used to close the future when lifetime expires
+ private Thread timeoutThread;
+
+ /**
+ * Basic constructor, sets a default timeout value and uses all scopes definied in CONFIG
+ */
+ public ThreadedReplyFuture(){
+ //TODO: which wait time should we use here? has to be larger than the time it takes to start and end the multicast convergence
+ this(SLPCore.CONFIG.getWaitTime()*5);
+ }
+
+
+
+
+ /**
+ * Constructor with a specific lifetime. The future expects to handle all scopes defined in CONFIG
+ *
+ * @param lifetime
+ * Number of milliseconds this future should remain open to receive results.
+ */
+ public ThreadedReplyFuture(long lifetime){
+ unhandledScopes = SLPUtils.stringToList(SLPCore.CONFIG.getScopes().toLowerCase(), ",");
+ timeout = System.currentTimeMillis()+lifetime;
+ timeoutThread = new TimeoutThread();
+ }
+
+
+ /**
+ * Detailed constructor.
+ *
+ * @param lifetime
+ * Number of milliseconds this future should remain open to receive results.
+ * @param scopes
+ * List of scopes to be handled.
+ */
+ public ThreadedReplyFuture(long lifetime,List<String> scopes){
+ for (String s : scopes){
+ unhandledScopes.add(s.toLowerCase());
+ }
+ timeout = System.currentTimeMillis()+lifetime;
+ timeoutThread = new TimeoutThread();
+ }
+
+
+
+ /**
+ * Adds the result of an SLP reply message to the list of responses and the sender of the
+ * reply to the list of responders, if the error code is 0.
+ *
+ * @param reply
+ * An AbstractSLPReplyMessage obtained through unicast or multicast
+ */
+ public void add(AbstractSLPReplyMessage reply){
+
+ if (reply==null || reply.getErrorCode()!=0){
+ return;
+ }
+ if (done){
+ // this reply is coming in too late...
+ return;
+ }
+
+ synchronized (responders){
+ if (!responders.contains(reply.getSource())) {
+ responders.add(reply.getSource());
+ } else {
+ return;
+ }
+ }
+
+ synchronized(responses){
+ List<String> res = reply.getResultAsList();
+ if (res!=null && res.size()>0){
+ List<String> resp = reply.getResultAsList();
+ for (String s: resp){
+ if (!responses.contains(s)){
+ responses.add(s);
+ }
+ }
+ responses.notifyAll();
+ }
+ }
+
+ }
+
+ /**
+ * Close the future.
+ * If the override flag is set, the future will be closed directly.
+ * If override is false, then the defined scopes will be removed from the list of unhandled scopes
+ * and the future will be closed only if no scopes remain unhandled. Else it will remain open.
+ *
+ * @param scopes
+ * The scopes to mark as done.
+ * @param override
+ * Set to true if the future should be closed even if scopes remain unhandled (e.g. timeout)
+ */
+ public synchronized void setDone(String[] scopes, boolean override){
+ synchronized (unhandledScopes){
+ for (String s: scopes){
+ unhandledScopes.remove(s.toLowerCase());
+ }
+ }
+
+ if (!unhandledScopes.isEmpty() && !override){
+ //oops, not all scopes that were expected to be handled actually were handled, so keep waiting
+ return;
+ }
+ if (!done){
+ done=true;
+ synchronized(donelock){
+ donelock.notifyAll();
+ }
+ synchronized(responses){
+ responses.notifyAll();
+ }
+ }
+ try {
+ timeoutThread.interrupt();
+ } catch (Exception e){
+ System.out.println("oops");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceLocationEnumeration#next()
+ */
+ public String next(){
+ // NOTE: a future is currently only read by one consumer (i.e. LocatorImpl) and therefor a single
+ // position marker is sufficient. Also the data containers holding responses must add new elements to the end.
+ synchronized(responses){
+ while (!done){
+ if (responses.size()>nextPosition){
+ return responses.get(nextPosition++);
+ }
+ try{
+ responses.wait(timeout-System.currentTimeMillis()+1000);
+ } catch (InterruptedException e){
+
+ }
+ }
+ if (responses.size()>nextPosition){
+ return responses.get(nextPosition++);
+ }
+ return null;
+ }
+ }
+
+
+ /**
+ * Returns the status of the future.
+ *
+ * @return
+ * True if done, false if results can still be added.
+ */
+ public synchronized boolean isDone(){
+ return done;
+ }
+
+
+ /**
+ * Blocking call that waits until the future is marked as "done" before returning all available responses.
+ *
+ * @return
+ * A list of all results obtained during the unicast or multicast SLP operation in the form of Strings.
+ */
+ public List<String> getResult(){
+ while (!done){
+ synchronized (donelock){
+ try {
+ donelock.wait();
+ } catch (InterruptedException ie){
+
+ }
+ }
+ }
+ return responses;
+ }
+
+
+ /**
+ * Returns the sources of all reply messages with error code 0 passed on to this future.
+ *
+ * @return
+ * Array of IP addresses as Strings in dot notation of the sources of reply messages.
+ */
+ public synchronized String[] getResponders(){
+ return SLPUtils.listToStringArray(responders);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Enumeration#hasMoreElements()
+ */
+ public synchronized boolean hasMoreElements() {
+ return (responses.size()>nextPosition);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Enumeration#nextElement()
+ */
+ public String nextElement() {
+ return next();
+ }
+
+
+
+ /**
+ * setup a new thread to close this future when it times out.
+ *
+ */
+ private class TimeoutThread extends Thread {
+
+ public TimeoutThread() {
+ this.start();
+ }
+
+ public void run() {
+
+ long remain;
+
+ // while lifetime is not expired
+ while (((remain=timeout-System.currentTimeMillis())>0) && !isDone()){
+ try {
+ Thread.sleep(remain);
+ } catch (InterruptedException ie){
+ continue;
+ }
+ }
+ // close the future, even if scopes remain unhandled
+ setDone(new String[]{},true);
+ }
+ }
+
+
+}
+
+
+
+
+
+
+
+
+
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/ThreadedReplyFuture.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemon.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemon.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemon.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemon.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,173 @@
+/*
+ * 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.directory.slp.impl.da;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directory.slp.Service;
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.ServiceStore;
+import org.apache.directory.slp.messages.AbstractSLPMessage;
+import org.apache.directory.slp.messages.AbstractSLPReplyMessage;
+import org.apache.directory.slp.messages.DAAdvertisementMessage;
+import org.apache.directory.slp.messages.ServiceDeregistrationMessage;
+import org.apache.directory.slp.messages.ServiceRegistrationMessage;
+
+
+/**
+ * Internal interface of the jSLP Directory Agent. This interface is to the "daemon" that does message handling
+ * and reads services from and writes them to the store. This should only be used by the jSLP machinery, not fro the outside.
+ * To access the DA from a client application, or to start a standalone DA, use the DirectoryAgent interface.
+ *
+ * @author Lorenz Breu
+ */
+public interface DirectoryAgentDaemon {
+
+ /**
+ * This does the actual message handling and controlling. Called by the SLPHandler if it receives a message
+ * of interest.
+ *
+ * @param msg
+ * The received AbstractSLPMessage
+ * @return
+ * The reply if the received message triggers such, null else.
+ * @throws ServiceLocationException
+ */
+ public AbstractSLPReplyMessage handleMessage(AbstractSLPMessage msg) throws ServiceLocationException;
+
+ /**
+ * Checks if the DA is set to handle requests in this specific scope.
+ *
+ * @param scope
+ * The scope to be checked
+ * @return
+ * True if the DA supports that scope, false otherwise
+ */
+ public boolean isInScope(String scope);
+
+ /**
+ * Builds the DAAdvertisementMessage.
+ *
+ * @return
+ * A DAAdvertisementMessage
+ * @throws ServiceLocationException
+ */
+ public DAAdvertisementMessage buildAdvert() throws ServiceLocationException;
+
+ /**
+ * Gets the statelessBootTimestamp of the DA
+ *
+ * @return
+ * statelessBootTimestamp
+ *
+ */
+ public int getStatelessBootTimestamp();
+
+ /**
+ * Sets the store that contains the registered services
+ *
+ * @param store
+ * An object that implements the ServiceStore interface
+ */
+ public void setStore(ServiceStore store);
+
+ /**
+ * Checks if a service with the given url has been registered with this DA
+ *
+ * @param service
+ * The service to be checked
+ * @return
+ * True if a service with that url has been found in the store
+ */
+ public boolean isKnownService(Service service);
+
+ /**
+ * Updates a registered service entry with new attributes.
+ *
+ * @param reg
+ * A ServiceRegistrationMessage which doesn't have the FRESH flag set.
+ * @throws ServiceLocationException
+ */
+ public void updateServiceEntry(ServiceRegistrationMessage reg) throws ServiceLocationException;
+
+ /**
+ * Register the service (if all checks pass) with the DA.
+ *
+ * @param reg
+ * A FRESH service registration message
+ * @throws ServiceLocationException
+ */
+ public void registerService(ServiceRegistrationMessage reg) throws ServiceLocationException;
+
+ /**
+ * Register the service (if all checks pass) with the DA. This method does not have to perform any
+ * checks, it just registers the service.
+ * @param reg
+ * The service to be registered
+ * @throws ServiceLocationException
+ */
+ public void registerService(Service service) throws ServiceLocationException;
+
+ /**
+ * Deregisters a service from the DA.
+ *
+ * @param dereg
+ * The ServiceDeregistrationMessage asking for the deregistration.
+ * @throws ServiceLocationException
+ */
+ public void deregisterService(ServiceDeregistrationMessage dereg) throws ServiceLocationException;
+
+ /**
+ * Deregisters a service from the DA.
+ *
+ * @param dereg
+ * The Service to be deregistered.
+ * @throws ServiceLocationException
+ */
+ public void deregisterService(Service service) throws ServiceLocationException;
+
+ /**
+ * Lists all services currently registered with the DA.
+ *
+ * @return
+ * A List of the service urls of all registered services.
+ */
+ public List<Service> listServices();
+
+ /**
+ * Shuts the DA down and sends a DAAdvert informing other SLP agents of this fact.
+ * All registered services are lost on shutdown.
+ */
+ public void shutdown();
+
+
+ /**
+ * Returns the mappings of attributes of specific abstract SLP service types to their type (string, integer, boolean, opaquevalue or array thereof)
+ * The method returns a copy of the actual type registry, changes made to the returned object are not
+ * reflected in the actual type registry
+ *
+ * @return
+ * A copy of the attribute type registry
+ * @throws ServiceLocationException
+ * If not implemented
+ */
+ public Map<String, Integer> getAttributeTypes() throws ServiceLocationException;
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemon.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemonImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemonImpl.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemonImpl.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemonImpl.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,1065 @@
+/*
+ * 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.directory.slp.impl.da;
+
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.directory.slp.Service;
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.ServiceStore;
+import org.apache.directory.slp.ServiceType;
+import org.apache.directory.slp.ServiceURL;
+import org.apache.directory.slp.extensions.AbstractExtension;
+import org.apache.directory.slp.extensions.AttributeListExtension;
+import org.apache.directory.slp.impl.AuthenticationBlock;
+import org.apache.directory.slp.impl.SLPCore;
+import org.apache.directory.slp.impl.SLPUtils;
+import org.apache.directory.slp.messages.AbstractSLPMessage;
+import org.apache.directory.slp.messages.AbstractSLPReplyMessage;
+import org.apache.directory.slp.messages.AbstractSLPRequestMessage;
+import org.apache.directory.slp.messages.AttributeReplyMessage;
+import org.apache.directory.slp.messages.AttributeRequestMessage;
+import org.apache.directory.slp.messages.DAAdvertisementMessage;
+import org.apache.directory.slp.messages.ServiceAcknowledgementMessage;
+import org.apache.directory.slp.messages.ServiceDeregistrationMessage;
+import org.apache.directory.slp.messages.ServiceRegistrationMessage;
+import org.apache.directory.slp.messages.ServiceReplyMessage;
+import org.apache.directory.slp.messages.ServiceRequestMessage;
+import org.apache.directory.slp.messages.ServiceTypeReplyMessage;
+import org.apache.directory.slp.messages.ServiceTypeRequestMessage;
+
+
+/**
+ *
+ * @author Lorenz Breu
+ */
+public class DirectoryAgentDaemonImpl extends SLPCore implements DirectoryAgentDaemon{
+
+ private static int statelessBootTimestamp;
+
+ //The storage mechanism holding the information on registered services
+ private ServiceStore store;
+
+ private boolean running = false;
+
+ // The scopes supported by this DA
+ private List<String> myScopes = new ArrayList<String>();
+
+ /**
+ * Sorted set for disposal of services which lifetimes have expired:
+ *
+ * Long expirationTimestamp -> String service.
+ */
+ private SortedMap<Long,String> serviceDisposalQueue = new TreeMap<Long,String>();
+
+ // The attributes of the DA as specified in the configuration
+ private String[] attributes = new String[]{};
+
+ public DirectoryAgentDaemonImpl() throws Exception{
+ statelessBootTimestamp = (int) System.currentTimeMillis();
+ attributes = SLPUtils.stringToStringArray(SLPCore.CONFIG.getConfigDAAttributes(), ",");
+ // load the scopes this DA is responsible for
+ myScopes = SLPUtils.stringToList(SLPCore.CONFIG.getScopes().toLowerCase(), ",");
+ running=true;
+
+ new UnsolicitedAdvertisementThread();
+ new ServiceDisposalThread();
+ SLPCore.platform.logDebug("jSLP directory agent starting...");
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#listServices()
+ */
+ public List<Service> listServices(){
+ try {
+ return store.listServices();
+ } catch (ServiceLocationException sle){
+ return new ArrayList<Service>();
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#isInScope(java.lang.String)
+ */
+ public boolean isInScope(String scope){
+ for (String s: myScopes){
+ if (s.toLowerCase().equals(scope.toLowerCase())){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#isKnownService(ch.ethz.iks.slp.impl.Service)
+ */
+ public boolean isKnownService(Service service){
+ return (store.containsService(service.getURL().toString()));
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#handleMessage(ch.ethz.iks.slp.messages.AbstractSLPMessage)
+ */
+ public AbstractSLPReplyMessage handleMessage(AbstractSLPMessage message) throws ServiceLocationException{
+ if (message == null || !(message instanceof AbstractSLPMessage)) {
+ return null;
+ }
+ AbstractSLPMessage msg = (AbstractSLPMessage) message;
+ boolean scopeOverlap = stripUnsupportedScopes(msg);
+ switch (msg.getFuncID()) {
+ case AbstractSLPMessage.DAADVERT:
+ // for now drop message as the handler does the necessary things for UA/SA
+
+ //TODO: keep a list of other DAs for coordination, replication, etc...
+
+ return null;
+
+ // reply messages not care about, we do...
+ case AbstractSLPMessage.ATTRRPLY:
+ case AbstractSLPMessage.SRVRPLY:
+ case AbstractSLPMessage.SRVTYPERPLY:
+
+ return null;
+ // request messages
+ case AbstractSLPMessage.SRVRQST:
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ ServiceReplyMessage servreply = new ServiceReplyMessage();
+ servreply.setXid(msg.getXid());
+ servreply.setLocale(msg.getLocale());
+ servreply.setErrorCode(ServiceLocationException.OPTION_NOT_UNDERSTOOD);
+ return servreply;
+ }
+
+ ServiceRequestMessage srvReq = (ServiceRequestMessage) msg;
+ if (!scopeOverlap){
+ return null;
+ }
+ if (srvReq.getServiceType().toString().equals("service:directory-agent")){
+ for (String s:srvReq.getScopes()){
+ if (isInScope(s)){
+ try {
+ DAAdvertisementMessage advert = buildAdvert();
+ advert.setXid(srvReq.getXid());
+ if (SLPCore.CONFIG.getSecurityEnabled()){
+ List<String> mySpis = SLPUtils.stringToList(SLPCore.CONFIG.getSPI(), ",");
+ boolean knownSpi = false;
+ for (String spi : srvReq.getSPIs()){
+ if (mySpis.contains(spi)){
+ knownSpi = true;
+ break;
+ }
+ }
+ if (knownSpi){
+ advert.setSPIs(SLPUtils.stringToStringArray(SLPCore.CONFIG.getSPI(), ","));
+ advert.sign(SLPCore.CONFIG.getSPI());
+ return advert;
+ }
+ // spi not supported
+ advert.setErrorCode(ServiceLocationException.AUTHENTICATION_UNKNOWN);
+
+
+ }
+ return advert;
+ } catch (ServiceLocationException sle){
+ // something went wrong internally, can't reply :(
+ return null;
+ }
+ }
+ }
+ // scopes not supported, drop silently
+ return null;
+ }// end of directory-agent lookup reply
+
+
+ ServiceReplyMessage servreply = new ServiceReplyMessage();
+ servreply.setXid(srvReq.getXid());
+ servreply.setLocale(srvReq.getLocale());
+
+ if (SLPCore.CONFIG.getSecurityEnabled()) {
+ boolean knownSpi = false;
+ List<String> knownSpis = SLPUtils.stringToList(SLPCore.CONFIG.getSPI(), ",");
+ for (String s : srvReq.getSPIs()){
+ if (knownSpis.contains(s)){
+ knownSpi = true;
+ break;
+ }
+ }
+ if (!knownSpi){
+ servreply.setErrorCode(ServiceLocationException.AUTHENTICATION_UNKNOWN);
+ return servreply;
+ }
+ }
+ List<String> overlap = new ArrayList<String>();
+ for (String scope : srvReq.getScopes()){
+ if (isInScope(scope)){
+ overlap.add(scope);
+ }
+ }
+ List<ServiceURL> results = new ArrayList<ServiceURL>();
+ List<AbstractExtension> extensions = new ArrayList<AbstractExtension>();
+ List<Service> services = store.getServices(srvReq.getServiceType().toString(),srvReq.getPredicate(),overlap.toArray(new String[]{}));
+ for (Service s : services){
+ if (!results.contains(s.getURL())){
+ results.add(s.getURL());
+ if (srvReq.hasExtensionType(AbstractExtension.ATTRIBUTE_LIST_EXTENSION)){
+ AttributeListExtension ale = new AttributeListExtension(s.getURL().toString(),SLPUtils.dictToString(s.getAttributesAsStringDict()));
+ extensions.add(ale);
+ }
+ }
+ }
+
+ /*
+ * if there is no result, don't send a reply. This causes the SA to
+ * get the same message at least two more times but the RFC strictly
+ * demands this for multicast requests
+ */
+ if (results.size() == 0 && srvReq.isMulticast()) {
+ return null;
+ }
+
+ servreply.setErrorCode((short) 0);
+ servreply.setServiceURLs(results.toArray(new ServiceURL[]{}));
+ servreply.setExtensions(extensions.toArray(new AbstractExtension[]{}));
+
+ if (SLPCore.CONFIG.getSecurityEnabled()) {
+ servreply.sign(SLPUtils.arrayToString(srvReq.getSPIs(),","));
+ }
+
+ return servreply;
+
+ case AbstractSLPMessage.ATTRRQST:
+
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ AttributeReplyMessage attreply = new AttributeReplyMessage();
+ attreply.setXid(msg.getXid());
+ attreply.setLocale(msg.getLocale());
+ attreply.setErrorCode(ServiceLocationException.OPTION_NOT_UNDERSTOOD);
+ return attreply;
+ }
+
+ AttributeRequestMessage attreq = (AttributeRequestMessage) msg;
+ if (!scopeOverlap){
+ return null;
+ }
+ //moved this out of the for loop for performance
+// the request can either be for a ServiceURL or a ServiceType
+ Object reqService;
+ boolean fullurl = false;
+ if ((attreq.getServiceUrl().getURL().indexOf("//") == -1) || (attreq.getServiceUrl().getHost().equals("nullnull"))) {
+ reqService = attreq.getServiceUrl().getServiceType();
+ } else {
+ fullurl = true;
+ reqService = new ServiceURL(attreq.getServiceUrl().getURL(), 0);
+ }
+ String[] attResult = store.getAttributes(reqService.toString(),attreq.getTags(), attreq.getScopes());
+ if (!fullurl){
+ attResult=SLPUtils.mergeAttributes(attResult);
+ }
+ AttributeReplyMessage attrep = new AttributeReplyMessage();
+ attrep.setAttributes(SLPUtils.mergeAttributes(attResult));
+ attrep.setLocale(attreq.getLocale());
+ attrep.setXid(attreq.getXid());
+ attrep.setAuthBlocks(new AuthenticationBlock[0]);
+ attrep.setErrorCode((short)0);
+ if (attreq.getSPIs().length>0 && !fullurl){
+ attrep.setAttributes(new String[]{});
+ attrep.setErrorCode(ServiceLocationException.AUTHENTICATION_FAILED);
+ }
+
+
+
+ if (SLPCore.CONFIG.getSecurityEnabled()) {
+ attrep.sign(SLPUtils.arrayToString(attreq.getSPIs(),","));
+ }
+ return attrep;
+ case AbstractSLPMessage.SRVTYPERQST:
+
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ ServiceTypeReplyMessage streply = new ServiceTypeReplyMessage();
+ streply.setXid(msg.getXid());
+ streply.setLocale(msg.getLocale());
+ streply.setErrorCode(ServiceLocationException.OPTION_NOT_UNDERSTOOD);
+ return streply;
+ }
+
+ ServiceTypeRequestMessage streq = (ServiceTypeRequestMessage) msg;
+ if (!scopeOverlap){
+ return null;
+ }
+ ServiceType[] result = store.getServiceTypes(streq.getScopes(),streq.getNamingAuthority());
+
+
+ ServiceTypeReplyMessage streply = new ServiceTypeReplyMessage();
+ streply.setXid(streq.getXid());
+ streply.setLocale(streq.getLocale());
+ streply.setErrorCode((short)0);
+ streply.setServiceTypes(result);
+ return streply;
+
+ // registration and deregistration
+ case AbstractSLPMessage.SRVREG:
+ // process the message and check if everything is ok.
+ // then cache the service.
+
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ ServiceAcknowledgementMessage ack = new ServiceAcknowledgementMessage();
+ ack.setXid(msg.getXid());
+ ack.setLocale(msg.getLocale());
+ ack.setErrorCode(ServiceLocationException.OPTION_NOT_UNDERSTOOD);
+ return ack;
+ }
+
+ ServiceRegistrationMessage reg = (ServiceRegistrationMessage) msg;
+
+ ServiceAcknowledgementMessage ack = new ServiceAcknowledgementMessage();
+ ack.setXid(reg.getXid());
+ ack.setErrorCode((short) 0);
+
+ if (!reg.checkAttributeListValidity()){
+ ack.setErrorCode(ServiceLocationException.INVALID_REGISTRATION);
+ return ack;
+ }
+
+ Service service = new Service(reg);
+ boolean found = false;
+ for (int i=0;i<reg.getScopes().length;i++) {
+ String scope = reg.getScopes()[i];
+ scope = scope.toLowerCase().trim();
+
+ // is the DA configured for this scope?
+ if (myScopes.contains(scope)){
+ found = true;
+ break;
+ }
+
+ }
+
+ if (!found){
+ // reply with an error if not:
+ ack.setErrorCode(ServiceLocationException.SCOPE_NOT_SUPPORTED);
+ return ack;
+ }
+
+ try {
+ // is this a fresh registration, or an incremental one?
+ boolean exists = isKnownService(service);
+ if (exists){
+ updateServiceEntry(reg);
+ } else {
+ registerService(reg);
+ }
+ } catch (ServiceLocationException sle){
+ ack.setErrorCode(sle.getErrorCode());
+ }
+
+ return ack;
+
+
+
+
+
+ case AbstractSLPMessage.SRVDEREG:
+// process the message and check if everything is ok.
+ // then cache the service.
+
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ ack = new ServiceAcknowledgementMessage();
+ ack.setXid(msg.getXid());
+ ack.setLocale(msg.getLocale());
+ ack.setErrorCode(ServiceLocationException.OPTION_NOT_UNDERSTOOD);
+ return ack;
+ }
+
+ ServiceDeregistrationMessage dereg = (ServiceDeregistrationMessage) msg;
+
+ ack = new ServiceAcknowledgementMessage();
+ ack.setXid(dereg.getXid());
+ ack.setErrorCode((short) 0);
+
+ found = false;
+ for (int i=0;i<dereg.getScopes().length;i++) {
+ String scope = dereg.getScopes()[i];
+ scope = scope.toLowerCase().trim();
+
+ // is the DA configured for this scope?
+ if (myScopes.contains(scope)){
+ found = true;
+ break;
+ }
+
+ }
+
+ if (!found){
+ // reply with an error if not:
+ ack.setErrorCode(ServiceLocationException.SCOPE_NOT_SUPPORTED);
+ return ack;
+ }
+
+ try {
+ deregisterService(dereg);
+ } catch (ServiceLocationException sle){
+ ack.setErrorCode(sle.getErrorCode());
+ }
+
+ return ack;
+
+ case AbstractSLPMessage.SRVACK:
+ if (msg.hasUnsupportedMandatoryExtensions()){
+ return null;
+ }
+ final AbstractSLPReplyMessage rep = (AbstractSLPReplyMessage) msg;
+ if (rep.getErrorCode() != 0) {
+ SLPCore.platform.logWarning(msg.getSource()
+ + " replied with error code " + rep.getErrorCode()
+ + " (" + rep + ")");
+ }
+ SLPCore.addReply(msg, new InetSocketAddress(msg.getSource(),msg.getPort()));
+ return null;
+
+ default:
+
+ return null;
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#setStore(ch.ethz.iks.slp.impl.da.ServiceStore)
+ */
+ public void setStore(ServiceStore store){
+ // TODO: should dynamic switchover be allowed? in this case service must be extracted from the
+ // old store and injected into the new one...
+ this.store = store;
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#registerService(ch.ethz.iks.slp.messages.ServiceRegistrationMessage)
+ */
+ public void registerService(ServiceRegistrationMessage reg) throws ServiceLocationException{
+ // test for incremental registration has been done
+ if (SLPCore.CONFIG.getSecurityEnabled()){
+ // message has been authenticated
+ // dump all auth blocks that are not understood
+ List<AuthenticationBlock> auth = new ArrayList<AuthenticationBlock>();
+ List<String> mySpis = SLPUtils.stringToList(SLPCore.CONFIG.getSPI(),",");
+ for (AuthenticationBlock b : reg.getAuthBlocks()){
+ if (mySpis.contains(b.getSpi())){
+ auth.add(b);
+ }
+ }
+ reg.setAuthBlocks(auth.toArray(new AuthenticationBlock[]{}));
+ }
+
+
+
+ // first check if FRESH is NOT set but no service has been registered to update...
+ if (!reg.isFresh()){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_UPDATE,"Tried to register a new service without the FRESH flag set");
+ }
+
+
+ Service service = new Service(reg);
+
+
+ store.storeService(service);
+
+ if (reg.getServiceURL().getLifetime() > ServiceURL.LIFETIME_PERMANENT) {
+ synchronized (serviceDisposalQueue) {
+ long next = System.currentTimeMillis()
+ + (reg.getServiceURL().getLifetime() * 1000);
+ ArrayList<Long> keys = new ArrayList<Long>(serviceDisposalQueue
+ .keySet());
+ for (Iterator iter = keys.iterator(); iter.hasNext();) {
+ Object key = iter.next();
+ if (serviceDisposalQueue.get(key).equals(reg.getServiceURL().toString())) {
+ serviceDisposalQueue.remove(key);
+ }
+ }
+ serviceDisposalQueue.put(new Long(next), reg.getServiceURL().toString());
+ serviceDisposalQueue.notifyAll();
+ }
+ }
+
+ SLPCore.platform.logTraceReg("REGISTERED " + reg.getServiceURL());
+
+ // TODO: pass on registration to fellow DAs ???
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#registerService(ch.ethz.iks.slp.impl.Service)
+ */
+ public void registerService(Service service) throws ServiceLocationException{
+ // this call should only be made through the DirectoryAgent interface
+ // no checks are made
+
+ store.storeService(service);
+
+ if (service.getURL().getLifetime() > ServiceURL.LIFETIME_PERMANENT) {
+ synchronized (serviceDisposalQueue) {
+ long next = System.currentTimeMillis()
+ + (service.getURL().getLifetime() * 1000);
+ ArrayList<Long> keys = new ArrayList<Long>(serviceDisposalQueue
+ .keySet());
+ for (Iterator iter = keys.iterator(); iter.hasNext();) {
+ Object key = iter.next();
+ if (serviceDisposalQueue.get(key).equals(service.getURL().toString())) {
+ serviceDisposalQueue.remove(key);
+ }
+ }
+ serviceDisposalQueue.put(new Long(next), service.getURL().toString());
+ serviceDisposalQueue.notifyAll();
+ }
+ }
+
+ SLPCore.platform.logTraceReg("REGISTERED " + service.getURL());
+
+ // TODO: pass on registration to fellow DAs ???
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#deregisterService(ch.ethz.iks.slp.messages.ServiceDeregistrationMessage)
+ */
+ public void deregisterService(ServiceDeregistrationMessage dereg) throws ServiceLocationException{
+
+ Service registeredService = store.getService(dereg.getServiceURL().toString());
+
+ if (registeredService==null){
+ // no specs for this case given in RFC2608...
+ throw new ServiceLocationException(ServiceLocationException.INVALID_REGISTRATION,"No such Service registered");
+ }
+
+ //check if the <scope-list> matches the one used in previous registration
+ List<String> previousScopes = registeredService.getScopes();
+ if (previousScopes.size()!=dereg.getScopes().length){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to deregister an existing entry registered with a different scope-list");
+ }
+ for (String scope: dereg.getScopes()){
+ if (!previousScopes.contains(scope.toLowerCase().trim())){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to deregister an existing entry registered with a different scope-list");
+ }
+ }
+
+ // check if tag-list is non-zero, in which case only the attributes in the tag list are deleted
+ if (dereg.getTags().length>0){
+ if (registeredService.getAuthBlocks().length>0){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_FAILED, "Tried to deregister attributes of an existing entry registered with authentication blocks");
+ }
+
+ Dictionary<String,String> attributes = registeredService.getAttributesAsStringDict();
+ // find all matching attributes in the services attribute dictionary...
+ List<String> matches = SLPUtils.findMatches(SLPUtils.arrayToList(dereg.getTags()), attributes);
+ // and extract the attribute types...
+ for (String s : matches){
+ // s is of form "(ATTRIBUTE)" or "(ATTRIBUTE=VALUE)"
+ int end = s.length()-1;
+ if (s.indexOf("=")>-1){
+ end = s.indexOf("=");
+ }
+ String q = s.substring(1,end);
+ registeredService.getAttributes().remove(q);
+ }
+
+
+
+ store.deleteService(dereg.getServiceURL().toString());
+ store.storeService(registeredService);
+ SLPCore.platform.logTraceReg("DEREGISTERED ATTRIBUTES ["+dereg.getTags()+"] from " + dereg.getServiceURL());
+ return;
+ }
+
+
+ if (registeredService.getURL().getAuthBlocks().length>0){
+ // unsure about what RFC 2608 means in the part concerning this...
+
+ // fetch all spis for this reg message
+ AuthenticationBlock[] authBlocks = dereg.getServiceURL().getAuthBlocks();
+ String[] spis = new String[authBlocks.length];
+ for (int i = 0; i< authBlocks.length; i++){
+ spis[i] = authBlocks[i].getSpi();
+ }
+ // now get the spis of the stored service
+ AuthenticationBlock[] registeredAuthBlocks = registeredService.getURL().getAuthBlocks();
+ String[] registeredSpis = new String[registeredAuthBlocks.length];
+ for (int i = 0; i< registeredAuthBlocks.length; i++){
+ registeredSpis[i] = registeredAuthBlocks[i].getSpi();
+ }
+ if (registeredSpis.length!=spis.length){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_FAILED,"SPIs did not match existing entry");
+ }
+ for (int i = 0;i<spis.length;i++){
+ boolean found = false;
+ // yes, this runs in O(n²), may be fixed later if possible
+ for (int j=0;j<registeredSpis.length;j++){
+ if (spis[i].equals(registeredSpis[j])){
+ found=true;
+ }
+ }
+ if (!found){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_FAILED,"SPIs did not match existing entry");
+ }
+ }
+
+ } // end of security enabled block
+
+ store.deleteService(dereg.getServiceURL().toString());
+
+ serviceDisposalQueue.values().remove(dereg.getServiceURL().toString());
+
+
+ SLPCore.platform.logTraceReg("DEREGISTERED " + dereg.getServiceURL());
+
+ // TODO: pass on deregistration to fellow DAs ???
+ }
+
+
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#deregisterService(ch.ethz.iks.slp.impl.Service)
+ */
+ public void deregisterService(Service service) throws ServiceLocationException{
+
+ store.deleteService(service.getURL().toString());
+
+ serviceDisposalQueue.values().remove(service.getURL().toString());
+
+ SLPCore.platform.logTraceReg("DEREGISTERED " + service.getURL());
+
+ // TODO: pass on deregistration to fellow DAs ???
+ }
+
+
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#updateServiceEntry(ch.ethz.iks.slp.messages.ServiceRegistrationMessage)
+ */
+ public void updateServiceEntry(ServiceRegistrationMessage reg) throws ServiceLocationException{
+ // this is an update, so let's first fetch the existing service
+ Service registeredService = store.getService(reg.getServiceURL().toString());
+
+ // if the resh flag is set, overwrite the existing entry
+ if (reg.isFresh()){
+ try {
+// check if the <scope-list> matches the one used in previous registration
+ List<String> previousScopes = registeredService.getScopes();
+ if (previousScopes.size()!=reg.getScopes().length){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to update an existing entry registered with a different scope-list");
+ }
+ for (String scope: reg.getScopes()){
+ if (!previousScopes.contains(scope.toLowerCase().trim())){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to update an existing entry registered with a different scope-list");
+ }
+ }
+ // check if the slp spis are identical to the ones previously used
+ if (SLPCore.CONFIG.getSecurityEnabled()){
+ // fetch all spis for this reg message
+ AuthenticationBlock[] authBlocks = reg.getAuthBlocks();
+ String[] spis = new String[authBlocks.length];
+ for (int i = 0; i< authBlocks.length; i++){
+ spis[i] = authBlocks[i].getSpi();
+ }
+ // now get the spis of the stored service
+ AuthenticationBlock[] registeredAuthBlocks = registeredService.getAuthBlocks();
+ String[] registeredSpis = new String[registeredAuthBlocks.length];
+ for (int i = 0; i< registeredAuthBlocks.length; i++){
+ registeredSpis[i] = registeredAuthBlocks[i].getSpi();
+ }
+ if (registeredSpis.length!=spis.length){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_UPDATE,"SPIs did not match existing entry");
+ }
+ for (int i = 0;i<spis.length;i++){
+ boolean found = false;
+ // yes, this runs in O(n²), may be fixed later if possible
+ for (int j=0;j<registeredSpis.length;j++){
+ if (spis[i].equals(registeredSpis[j])){
+ found=true;
+ }
+ }
+ if (!found){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_ABSENT,"SPIs did not match existing entry");
+ }
+ }
+
+ }
+
+ // scope checks out, security checks out, replace it
+
+ store.deleteService(reg.getServiceURL().toString());
+ store.storeService(new Service(reg));
+ SLPCore.platform.logTraceReg("REREGISTERED " + reg.getServiceURL());
+ return;
+ } catch (ServiceLocationException sle){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Problems updating service "+reg.getServiceURL());
+ }
+ } else {
+ // incremental update required
+
+ // first: check if there even exists a previous entry
+ if (registeredService==null){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_UPDATE, "Tried to update a non-existing entry");
+ }
+
+ // second: check if the service was previously registered with auth blocks
+ if (registeredService.getAuthBlocks().length > 0){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_FAILED, "Tried to update an existing entry registered with AuthBlocks");
+ }
+
+ // third: check if the <scope-list> matches the one used in previous registration
+ List<String> previousScopes = registeredService.getScopes();
+ if (previousScopes.size()!=reg.getScopes().length){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to update an existing entry registered with a different scope-list");
+ }
+ for (String scope: reg.getScopes()){
+ if (!previousScopes.contains(scope.toLowerCase().trim())){
+ throw new ServiceLocationException(ServiceLocationException.SCOPE_NOT_SUPPORTED, "Tried to update an existing entry registered with a different scope-list");
+ }
+ }
+
+ // fourth: check if the service-type is the same as previously registered
+ if (!registeredService.getURL().getServiceType().equals(reg.getServiceType())){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_UPDATE, "Tried to update an existing entry registered with a different service type");
+ }
+
+ // finally, check if the slp spis are identical to the ones previously used
+ if (SLPCore.CONFIG.getSecurityEnabled()){
+ // fetch all spis for this reg message
+ AuthenticationBlock[] authBlocks = reg.getAuthBlocks();
+ String[] spis = new String[authBlocks.length];
+ for (int i = 0; i< authBlocks.length; i++){
+ spis[i] = authBlocks[i].getSpi();
+ }
+ // now get the spis of the stored service
+ AuthenticationBlock[] registeredAuthBlocks = registeredService.getAuthBlocks();
+ String[] registeredSpis = new String[registeredAuthBlocks.length];
+ for (int i = 0; i< registeredAuthBlocks.length; i++){
+ registeredSpis[i] = registeredAuthBlocks[i].getSpi();
+ }
+ if (registeredSpis.length!=spis.length){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_UPDATE,"SPIs did not match existing entry");
+ }
+ for (int i = 0;i<spis.length;i++){
+ boolean found = false;
+ // yes, this runs in O(n²), may be fixed later if possible
+ for (int j=0;j<registeredSpis.length;j++){
+ if (spis[i].equals(registeredSpis[j])){
+ found=true;
+ }
+ }
+ if (!found){
+ throw new ServiceLocationException(ServiceLocationException.AUTHENTICATION_ABSENT,"SPIs did not match existing entry");
+ }
+ }
+
+ } // end of security enabled block
+
+
+
+ Dictionary<String,Object> registeredAttributes = registeredService.getAttributes();
+ Dictionary<String,Object> newAttributes = SLPUtils.stringArrayToDict(reg.getAttrList());
+ Enumeration<String> keys = newAttributes.keys();
+ while (keys.hasMoreElements()){
+ String key = keys.nextElement();
+ registeredAttributes.remove(key);
+ registeredAttributes.put(key, newAttributes.get(key));
+ }
+ registeredService.setAttributes(registeredAttributes);
+ } // end of incremental update
+
+ // process the new lifetime
+ if (reg.getServiceURL().getLifetime() > ServiceURL.LIFETIME_PERMANENT) {
+ synchronized (serviceDisposalQueue) {
+ long next = System.currentTimeMillis()
+ + (reg.getServiceURL().getLifetime() * 1000);
+ ArrayList<Long> disposalKeys = new ArrayList<Long>(serviceDisposalQueue.keySet());
+ for (Long k:disposalKeys) {
+ if (serviceDisposalQueue.get(k).equals(reg.getServiceURL().toString())) {
+ serviceDisposalQueue.remove(k);
+ }
+ }
+ serviceDisposalQueue.put(new Long(next), reg.getServiceURL().toString());
+ serviceDisposalQueue.notifyAll();
+ }
+ }
+ store.deleteService(reg.getServiceURL().toString());
+ store.storeService(registeredService);
+ SLPCore.platform.logTraceReg("REGISTERED INCREMENTALLY " + reg.getServiceURL());
+ return;
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#buildAdvert()
+ */
+ public DAAdvertisementMessage buildAdvert() throws ServiceLocationException{
+ DAAdvertisementMessage advert = new DAAdvertisementMessage();
+ // always return 0... what errors have to be handled here?
+ advert.setErrorCode((short) 0);
+ advert.setXid((short) 0);
+ advert.setStatelessBootTimestamp(statelessBootTimestamp);
+ advert.setAttributes(attributes);
+ //TODO: add min-refresh-interval here
+ ServiceURL myService = new ServiceURL("service:directory-agent://"+SLPCore.getMyIP().getHostAddress(),0);
+ advert.setServiceURL(myService);
+ advert.setOrigURL("service:directory-agent://"+SLPCore.getMyIP().getHostAddress());
+ advert.setScopes(SLPUtils.stringToStringArray(SLPCore.CONFIG.getScopes(), ","));
+
+ return advert;
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#getStatelessBootTimestamp()
+ */
+ public int getStatelessBootTimestamp(){
+ return statelessBootTimestamp;
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#shutdown()
+ */
+ public void shutdown(){
+ try {
+ if (running){
+ running = false;
+ SLPCore.platform.logDebug("jSLP Directory Agent shutting down...");
+ DAAdvertisementMessage advert = buildAdvert();
+ advert.setStatelessBootTimestamp(0);
+ SLPCore.sendUnicastMessage(advert, new InetSocketAddress(SLPCore.MCAST_ADDRESS,SLP_PORT), false);
+ SLPCore.shutdownDirectoryAgent();
+ //store.clear();
+ }
+
+ } catch (ServiceLocationException sle){
+ SLPCore.platform.logError("Error while closing down DA", sle);
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.impl.da.DirectoryAgentDaemon#getAttributeTypes()
+ */
+ public Map<String, Integer> getAttributeTypes() throws ServiceLocationException{
+ return store.getAttributeTypes();
+ }
+
+
+ /**
+ * This removes all unsupported scopes from the list of scopes in a message. After processing a message
+ * the scopelist in the message includes only those scopes the DA also supports.
+ *
+ * @param msg
+ * An AbstractSLPMessage, such as a ServiceRegistrationMessage
+ * @return
+ * True if the list of supported scopes still contains an entry, false if none of the scopes
+ * listed in the message are supported by the DA.
+ */
+ private boolean stripUnsupportedScopes(AbstractSLPMessage msg){
+ if (msg instanceof ServiceRegistrationMessage){
+ ServiceRegistrationMessage reg = (ServiceRegistrationMessage) msg;
+ List<String> supportedScopes = new ArrayList<String>();
+ for (String s: reg.getScopes()){
+ if (myScopes.contains(s.toLowerCase().trim())){
+ supportedScopes.add(s.toLowerCase().trim());
+ }
+ }
+ reg.setScopes(SLPUtils.listToStringArray(supportedScopes));
+ return (supportedScopes.size()>0);
+ }
+ if (msg instanceof ServiceDeregistrationMessage){
+ ServiceDeregistrationMessage reg = (ServiceDeregistrationMessage) msg;
+ List<String> supportedScopes = new ArrayList<String>();
+ for (String s: reg.getScopes()){
+ if (myScopes.contains(s.toLowerCase().trim())){
+ supportedScopes.add(s.toLowerCase().trim());
+ }
+ }
+ reg.setScopes(SLPUtils.listToStringArray(supportedScopes));
+ return (supportedScopes.size()>0);
+ }
+
+ if (msg instanceof AbstractSLPRequestMessage){
+ AbstractSLPRequestMessage req = (AbstractSLPRequestMessage) msg;
+ List<String> supportedScopes = new ArrayList<String>();
+ for (String s: req.getScopes()){
+ if (myScopes.contains(s.toLowerCase().trim())){
+ supportedScopes.add(s.toLowerCase().trim());
+ }
+ }
+ req.setScopes(SLPUtils.listToStringArray(supportedScopes));
+ return (supportedScopes.size()>0);
+ }
+ return true;
+ }
+
+
+
+
+ /**
+ * service disposal thread. Removes services from the local registry when
+ * their lifetime has expired.
+ */
+ private final class ServiceDisposalThread extends Thread {
+
+ /**
+ * create and start a new instance of this thread.
+ *
+ */
+ private ServiceDisposalThread() {
+ super("ServiceDisposalThread");
+ start();
+ }
+
+ /**
+ * thread's main loop.
+ */
+ public void run() {
+ try {
+ while (running) {
+ synchronized (serviceDisposalQueue) {
+ if (serviceDisposalQueue.isEmpty()) {
+ // nothing to do, sleep until something arrives
+ SLPCore.platform
+ .logDebug("ServiceDisposalThread sleeping ...");
+ serviceDisposalQueue.wait();
+ } else {
+ // we have work, do everything that is due
+ Long nextActivity;
+ while (!serviceDisposalQueue.isEmpty()
+ && (nextActivity = ((Long) serviceDisposalQueue
+ .firstKey())).longValue() <= System
+ .currentTimeMillis()) {
+
+ String service = serviceDisposalQueue
+ .get(nextActivity);
+
+ try {
+ store.deleteService(service);
+ } catch (ServiceLocationException sle) {
+ SLPCore.platform.logError(sle
+ .getMessage(), sle
+ .fillInStackTrace());
+ }
+ SLPCore.platform
+ .logTraceReg("disposed service "
+ + service);
+ serviceDisposalQueue.remove(nextActivity);
+ }
+ if (!serviceDisposalQueue.isEmpty()) {
+ /*
+ * there are some activities in the future,
+ * sleep until the first activity becomes due
+ */
+ nextActivity = ((Long) serviceDisposalQueue
+ .firstKey());
+ long waitTime = nextActivity.longValue()
+ - System.currentTimeMillis();
+ if (waitTime > 0) {
+ SLPCore.platform
+ .logDebug("sleeping for "
+ + waitTime / 1000
+ + " seconds.");
+ serviceDisposalQueue.wait(waitTime);
+ }
+ }
+ }
+ }
+ }
+ } catch (InterruptedException ie) {
+ // let the thread stop.
+ }
+ }
+ }
+
+
+ /**
+ * thread for unsolicited DAAdverts. This thread periodically sends out DAAdvertisements
+ */
+ private final class UnsolicitedAdvertisementThread extends Thread {
+
+ private long lastUnsolicitedAdvertisement = 0;
+
+ /**
+ * create and start a new instance of this thread.
+ *
+ */
+ private UnsolicitedAdvertisementThread() {
+ super("UnsolicitedAdvertisementThread");
+ start();
+ }
+
+ /**
+ * thread's main loop.
+ */
+ public void run() {
+ long remaining;
+ while (running){
+ try {
+ if ((remaining=SLPCore.CONFIG.getConfigDABeat()-System.currentTimeMillis()+lastUnsolicitedAdvertisement)<0){
+ DAAdvertisementMessage advert = buildAdvert();
+ if (SLPCore.CONFIG.getSecurityEnabled()){
+ advert.setSPIs(SLPUtils.stringToStringArray(SLPCore.CONFIG.getSPI(),","));
+ advert.sign(SLPCore.CONFIG.getSPI());
+ if (advert.getSize()>CONFIG.getMTU()){
+ //crap, too big, have to send a bunch of individual small ones...
+ String[] spis = SLPUtils.stringToStringArray(SLPCore.CONFIG.getSPI(), ",");
+ for (String spi : spis){
+ advert.setSPIs(new String[]{spi});
+ advert.sign(spi);
+ InetSocketAddress addr = new InetSocketAddress(SLP_MCAST_ADDRESS,SLP_PORT);
+ SLPCore.sendUnicastMessage(advert, addr, false);
+ }
+ lastUnsolicitedAdvertisement = System.currentTimeMillis();
+ continue;
+ }
+ }
+ InetSocketAddress addr = new InetSocketAddress(SLP_MCAST_ADDRESS,SLP_PORT);
+ SLPCore.sendUnicastMessage(advert, addr, false);
+ lastUnsolicitedAdvertisement = System.currentTimeMillis();
+ } else {
+ Thread.sleep(remaining);
+ }
+ }catch (Exception e){
+ continue;
+ }
+ }
+ }
+ }
+
+
+
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentDaemonImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentImpl.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentImpl.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentImpl.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,233 @@
+/*
+ * 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.directory.slp.impl.da;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directory.slp.DirectoryAgent;
+import org.apache.directory.slp.Service;
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.ServiceStore;
+import org.apache.directory.slp.ServiceURL;
+import org.apache.directory.slp.impl.SLPCore;
+import org.apache.directory.slp.impl.SLPUtils;
+import org.apache.directory.slp.messages.ServiceDeregistrationMessage;
+import org.apache.directory.slp.messages.ServiceRegistrationMessage;
+
+
+/**
+ *
+ * @author Lorenz Breu
+ */
+public class DirectoryAgentImpl implements DirectoryAgent{
+
+ public DirectoryAgentImpl(){
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#listServices()
+ */
+ public List<Service> listServices() {
+ return SLPCore.daDaemon.listServices();
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#shutdown()
+ */
+ public void shutdown() {
+ SLPCore.getDirectoryAgentDaemon().shutdown();
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#registerService(ch.ethz.iks.slp.messages.ServiceRegistrationMessage)
+ */
+ public void registerService(ServiceRegistrationMessage reg) throws ServiceLocationException{
+ SLPCore.getDirectoryAgentDaemon().registerService(reg);
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#registerService(ch.ethz.iks.slp.Service)
+ */
+ public void registerService(Service service) throws ServiceLocationException {
+ SLPCore.getDirectoryAgentDaemon().registerService(service);
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#deregisterService(ch.ethz.iks.slp.messages.ServiceDeregistrationMessage)
+ */
+ public void deregisterService(ServiceDeregistrationMessage dereg) throws ServiceLocationException{
+ SLPCore.getDirectoryAgentDaemon().deregisterService(dereg);
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#deregisterService(ch.ethz.iks.slp.Service)
+ */
+ public void deregisterService(Service service) throws ServiceLocationException{
+ SLPCore.getDirectoryAgentDaemon().deregisterService(service);
+ }
+
+
+// #comment
+// ;comment
+// service-url,language-tag,lifetime,[service-type]<newline>
+// "scopes="[scope-list]<newline>
+// [attrid]"="val1<newline>
+// [attrid]"="val1,val2,val3<newline>
+// <newline>
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#registerServicesFromFile(java.io.File)
+ */
+ public void registerServicesFromFile(File file){
+ try {
+ BufferedReader input = new BufferedReader(new FileReader(file));
+ String line = null;
+ boolean parsingService = false;
+ Service service = null;
+ List<String> attributes = new ArrayList<String>();
+ while ((line = input.readLine()) != null){
+ if (line.startsWith("#") || line.startsWith(";")){
+ // just a comment
+ continue;
+ }
+ if (!parsingService){
+ String[] fields = line.split(",");
+ String url = fields[0];
+ //TODO: implement correct localization
+ //String lang = fields[1];
+ int lifetime = Integer.parseInt(fields[2]);
+ if (fields.length==4){
+ String type = fields[3];
+ service = new Service(new ServiceURL(type, lifetime));
+ } else {
+ service = new Service(new ServiceURL(url,lifetime));
+ }
+ parsingService = true;
+ continue;
+ }
+ if (line.equals("")){
+ service.setAttributes(SLPUtils.stringArrayToDict(SLPUtils.listToStringArray(attributes)));
+ SLPCore.getDirectoryAgentDaemon().registerService(service);
+ service = null;
+ attributes = new ArrayList<String>();
+ parsingService = false;
+ continue;
+ }
+ if (line.startsWith("scopes=") && parsingService){
+ String[] scopes = line.substring(7).split(",");
+ service.setScopes(SLPUtils.arrayToList(scopes));
+ continue;
+ }
+ if (parsingService){
+ attributes.add("("+line+")");
+ }
+
+ }
+
+
+ } catch (Exception e){
+ SLPCore.getPlatform().logError("Unable to parse registration file");
+ System.out.println("Unable to parse registration file "+file);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#exportServicesToFile(java.lang.String, boolean)
+ */
+ public void exportServicesToFile(String path, boolean append){
+ File file = null;
+ BufferedWriter out = null;
+ try {
+ file = new File(path);
+ out = new BufferedWriter(new FileWriter(file,append));
+ } catch (Exception e){
+ SLPCore.getPlatform().logError("Unable to open registration file for writing");
+ System.out.println("Unable to open registration file "+path+" for writing");
+ }
+
+ try{
+ List<Service> allServices = listServices();
+ for (Service service : allServices){
+ //TODO: iplement correct localization
+ out.write(service.getURL().toString()+","+SLPCore.DEFAULT_LOCALE+","+service.getURL().getLifetime());
+ out.newLine();
+ out.write("scopes="+SLPUtils.listToString(service.getScopes(),","));
+ out.newLine();
+ Enumeration<String> keys = service.getAttributesAsStringDict().keys();
+ while (keys.hasMoreElements()){
+ String key = keys.nextElement();
+ out.write(key+"="+service.getAttributesAsStringDict().get(key));
+ out.newLine();
+ }
+ out.newLine();
+ out.close();
+
+ }
+ } catch (Exception e){
+ SLPCore.getPlatform().logError("Unable to export to file");
+ System.out.println("Unable to export to file "+path);
+ }
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#setServiceStore(ch.ethz.iks.slp.ServiceStore, boolean)
+ */
+ public void setServiceStore(ServiceStore store, boolean flush) throws ServiceLocationException {
+ List<Service> services = new ArrayList<Service>();
+ if (!flush){
+ services = SLPCore.daDaemon.listServices();
+ }
+ SLPCore.daDaemon.setStore(store);
+ if (!flush){
+ for (Service s:services){
+ registerService(s);
+ }
+ }
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.DirectoryAgent#getAttributeTypes()
+ */
+ public Map<String, Integer> getAttributeTypes() throws ServiceLocationException{
+ return SLPCore.getDirectoryAgentDaemon().getAttributeTypes();
+ }
+
+
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/DirectoryAgentImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/SimpleServiceStore.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/SimpleServiceStore.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/SimpleServiceStore.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/SimpleServiceStore.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,323 @@
+/*
+ * 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.directory.slp.impl.da;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directory.slp.OpaqueValue;
+import org.apache.directory.slp.Service;
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.ServiceStore;
+import org.apache.directory.slp.ServiceType;
+import org.apache.directory.slp.ServiceURL;
+import org.apache.directory.slp.impl.SLPCore;
+import org.apache.directory.slp.impl.SLPUtils;
+import org.apache.directory.slp.impl.filter.Filter;
+
+
+/**
+ * A simple HashMap based ServiceStore for the DirectoryAgentDaemon to store registrations in.
+ *
+ * @author Lorenz Breu
+ */
+public class SimpleServiceStore implements ServiceStore{
+
+
+ // The services registered
+ private Map<String,Service> registeredServices = new HashMap<String,Service>();
+
+ // the type registry
+ private Map<String,Integer> attributeTypes = new HashMap<String, Integer>();
+
+
+
+ public SimpleServiceStore(){
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#deleteService(java.lang.String)
+ */
+ public synchronized void deleteService(String serviceurl) throws ServiceLocationException {
+ try {
+ registeredServices.remove(serviceurl);
+ } catch (Exception e){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Service not registered before.");
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getAttributes(java.lang.String, java.lang.String[], java.lang.String[])
+ */
+ public String[] getAttributes(String service, String[] tagList, String[] scopeList){
+ try {
+ List<Service> allServiceMatches = getServices(service, "",scopeList);
+
+
+ List<String> attResult = new ArrayList<String>();
+
+ for (Service matchedService: allServiceMatches) {
+ List<String> completeListwithDuplicates = SLPUtils.findMatches(SLPUtils.arrayToList(tagList), matchedService.getAttributesAsStringDict());
+
+ for (String s: completeListwithDuplicates){
+ if (!attResult.contains(s)){
+ attResult.add(s);
+ }
+ }
+
+ }
+
+
+
+ return attResult.toArray(new String[]{});
+ } catch (ServiceLocationException sle){
+ SLPCore.getPlatform().logError("error finding attributes", sle);
+ return new String[]{""};
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getServiceTypes(java.lang.String[], java.lang.String)
+ */
+ public ServiceType[] getServiceTypes(String[] scopes, String namingAuthority){
+ try {
+ List<Service> allServiceMatches = listServices();
+ List<Service> scopeMatchedServices = new ArrayList<Service>();
+ for (Service serv: allServiceMatches){
+ for (String scope : scopes){
+ if (serv.getScopes().contains(scope.toLowerCase().trim())){
+ scopeMatchedServices.add(serv);
+ break;
+ }
+ }
+
+ }
+
+ ArrayList<ServiceType> result = new ArrayList<ServiceType>();
+
+ for (Service service : scopeMatchedServices) {
+ ServiceType type = service.getURL().getServiceType();
+ if (namingAuthority.equals("*")
+ || namingAuthority.equals("")
+ || type.getNamingAuthority().equals(
+ namingAuthority)) {
+ if (!result.contains(type)) {
+ result.add(type);
+ }
+ }
+ }
+
+ return result.toArray(new ServiceType[]{});
+ } catch (ServiceLocationException sle){
+ SLPCore.getPlatform().logError("Error while retrieving service types", sle);
+ return new ServiceType[]{};
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getServices(java.lang.String, java.lang.String)
+ */
+ public List<Service> getServices(String serviceType,String attributeFilter) throws ServiceLocationException {
+ try {
+ return getServices(serviceType, attributeFilter, SLPUtils.stringToStringArray(SLPCore.CONFIG.getScopes(),","));
+ } catch (Exception e){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Error while retrieveing Services");
+ }
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getServices(java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public List<Service> getServices(String serviceType,String attributeFilter, String[] scopes) throws ServiceLocationException {
+ try {
+ List<String> scopeList = new ArrayList<String>();
+ for (String s: scopes){
+ scopeList.add(s.toLowerCase().trim());
+ }
+
+ Object st;
+ try{
+ st = new ServiceURL(serviceType,0);
+ } catch (Exception e){
+ st = new ServiceType(serviceType);
+ }
+ List<Service> results = new ArrayList<Service>();
+ synchronized(registeredServices){
+ for (String key : registeredServices.keySet()) {
+ Service service = registeredServices.get(key);
+
+ if (service.getURL().matches(st) && scopeMatch(service.getScopes(),scopeList)) {
+ if (attributeFilter == null || attributeFilter.equals("")) {
+
+ results.add(service);
+ continue;
+ }
+ Filter filter = SLPCore.getPlatform().createFilter(attributeFilter);
+ if (filter.match(service.getAttributes()) && scopeMatch(service.getScopes(),scopeList)) {
+ results.add(service);
+ }
+ }
+ }
+ }
+
+
+ return results;
+
+ } catch (Exception e){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Error while retrieveing Services");
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getService(java.lang.String)
+ */
+ public synchronized Service getService(String serviceUrl) throws ServiceLocationException{
+ try {
+ return registeredServices.get(serviceUrl);
+ } catch (Exception e){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Failed to find specified service");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#storeService(ch.ethz.iks.slp.Service)
+ */
+ public synchronized void storeService(Service service) throws ServiceLocationException {
+ if (registeredServices.get(service.getURL().toString())!=null){
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Service already exists");
+ }
+ String abstracttype = service.getURL().getServiceType().getAbstractTypeName();
+ if (abstracttype.equals("")){
+ abstracttype=service.getURL().toString();
+ abstracttype = abstracttype.substring(0,abstracttype.indexOf("://"));
+ ServiceType st = new ServiceType(abstracttype);
+ abstracttype=st.getAbstractTypeName();
+ }
+ if (abstracttype.startsWith("service:")){
+ abstracttype = abstracttype.substring("service:".length());
+ }
+ try {
+ if (service.getAttributes()!=null){
+ Enumeration<String> atts = service.getAttributes().keys();
+ while (atts.hasMoreElements()){
+ String k = atts.nextElement();
+ int type;
+ if ((service.getAttributes().get(k) instanceof Boolean) || service.getAttributes().get(k) instanceof Boolean[]){
+ type = BOOLEAN_AT;
+ } else if ((service.getAttributes().get(k) instanceof Number) || service.getAttributes().get(k) instanceof Number[]){
+ type = INTEGER_AT;
+ } else if ((service.getAttributes().get(k) instanceof OpaqueValue) || service.getAttributes().get(k) instanceof OpaqueValue[]){
+ type = OPAQUE_AT;
+ } else {
+ type=STRING_AT;
+ }
+ Integer at = attributeTypes.get(abstracttype+"."+k);
+ if (at!=null && at!=type){
+ throw new ServiceLocationException(ServiceLocationException.INVALID_REGISTRATION,"inconsistent attribute type");
+ }
+ attributeTypes.put(abstracttype+"."+k, type);
+
+ }
+ }
+ registeredServices.put(service.getURL().toString(),service);
+
+
+ } catch (Exception e){
+ if (e instanceof ServiceLocationException){
+ throw (ServiceLocationException) e;
+ }
+ throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"Problems while registering service");
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#containsService(java.lang.String)
+ */
+ public synchronized boolean containsService(String service) {
+ return registeredServices.containsKey(service);
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#listServices()
+ */
+ public synchronized List<Service> listServices() throws ServiceLocationException {
+ List<Service> result = new ArrayList<Service>();
+ for (Service service : registeredServices.values()){
+ result.add(service);
+ }
+ return result;
+ }
+
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#clear()
+ */
+ public synchronized void clear(){
+ registeredServices = new HashMap<String,Service>();
+ attributeTypes = new HashMap<String, Integer>();
+ }
+
+ /**
+ * Checks if there is a scope in both lists. Returns true if one of the two is null....
+ *
+ * @param scopes1
+ * A List of scopes strings
+ * @param scopes2
+ * A List of scopes strings
+ * @return
+ * True if either list is null or both lists contain at least one identical scope
+ * False if both lists contain unique scopes
+ */
+ private boolean scopeMatch(List<String> scopes1, List<String> scopes2){
+ if ((scopes1==null) || (scopes2==null)){
+ return true;
+ }
+ for (String s: scopes1){
+ if (scopes2.contains(s)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#shutdown()
+ */
+ public void shutdown(){
+ // nothing to do
+ }
+
+ /* (non-Javadoc)
+ * @see ch.ethz.iks.slp.ServiceStore#getAttributeTypes()
+ */
+ public Map<String, Integer> getAttributeTypes() throws ServiceLocationException{
+ return new HashMap<String, Integer>(attributeTypes);
+ }
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/da/SimpleServiceStore.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/filter/Filter.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/filter/Filter.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/filter/Filter.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/filter/Filter.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,41 @@
+/*
+ * 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.directory.slp.impl.filter;
+
+import java.util.Dictionary;
+
+/**
+ * a generic LDAP filter.
+ * @author Jan S. Rellermeyer
+ */
+public interface Filter {
+ /**
+ * try to match a <code>Dictionary</code> of attributes.
+ * @param values a <code>Dictionary</code> of attributes.
+ * @return true if the filter evaluated to true;
+ */
+ boolean match(Dictionary values);
+
+ /**
+ * get a String representation of the filter.
+ * @return the String representation.
+ */
+ String toString();
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/filter/Filter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPMessage.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPMessage.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPMessage.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPMessage.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,337 @@
+/*
+ * 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.directory.slp.messages;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.extensions.AbstractExtension;
+import org.apache.directory.slp.extensions.UnsupportedExtension;
+import org.apache.directory.slp.impl.SLPUtils;
+
+
+
+/**
+ * abstract base class for all SLP messages.
+ *
+ * @author Jan S. Rellermeyer
+ */
+public abstract class AbstractSLPMessage {
+
+ protected static final String[] EMPTY = new String[0];
+
+ protected final byte funcID;
+
+ protected short xid;
+
+ protected String source;
+ protected int port;
+
+ protected boolean multicast;
+ protected boolean fresh = true;;
+
+ protected boolean tcp;
+
+ protected AbstractExtension[] extensions = new AbstractExtension[]{};
+
+ /**
+ * the message funcID values according to RFC 2608, Service Request = 1.
+ */
+ public static final byte SRVRQST = 1;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Reply = 2.
+ */
+ public static final byte SRVRPLY = 2;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Registration =
+ * 3.
+ */
+ public static final byte SRVREG = 3;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Deregistration =
+ * 4.
+ */
+ public static final byte SRVDEREG = 4;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Acknowledgement =
+ * 5.
+ */
+ public static final byte SRVACK = 5;
+
+ /**
+ * the message funcID values according to RFC 2608, Attribute Request = 6.
+ */
+ public static final byte ATTRRQST = 6;
+
+ /**
+ * the message funcID values according to RFC 2608, Attribute Reply = 7.
+ */
+ public static final byte ATTRRPLY = 7;
+
+ /**
+ * the message funcID values according to RFC 2608, DA Advertisement = 8.
+ */
+ public static final byte DAADVERT = 8;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Type Request =
+ * 9.
+ */
+ public static final byte SRVTYPERQST = 9;
+
+ /**
+ * the message funcID values according to RFC 2608, Service Type Reply = 10.
+ */
+ public static final byte SRVTYPERPLY = 10;
+
+ /**
+ * the message funcID values according to RFC 2608, SA Advertisement = 11.
+ */
+ public static final byte SAADVERT = 11;
+
+ /**
+ * used for reverse lookup of funcID values to have nicer debug messages.
+ */
+ private static final String[] TYPES = { "NULL", "SRVRQST", "SRVPLY",
+ "SRVREG", "SRVDEREG", "SRVACK", "ATTRRQST", "ATTRRPLY", "DAADVERT",
+ "SRVTYPERQST", "SRVTYPERPLY", "SAADVERT" };
+
+ // TODO: take the default locale here...
+ protected Locale locale = new Locale("en");
+
+ AbstractSLPMessage(final byte funcID) {
+ this.funcID = funcID;
+ }
+
+ public final byte getFuncID() {
+ return funcID;
+ }
+
+ public final short getXid() {
+ return xid;
+ }
+
+ public final void setXid(final short xid) {
+ this.xid = xid;
+ }
+
+ public final boolean isMulticast() {
+ return multicast;
+ }
+
+ public final void setMulticast(final boolean multicast) {
+ this.multicast = multicast;
+ }
+
+
+ public boolean isFresh(){
+ return fresh;
+ }
+
+ public void setFresh(boolean freshness){
+ fresh = freshness;
+ }
+
+ public final boolean isTcp() {
+ return tcp;
+ }
+
+ public final void setTcp(final boolean tcp) {
+ this.tcp = tcp;
+ }
+
+ public final Locale getLocale() {
+ return locale;
+ }
+
+ public final void setLocale(final Locale locale) {
+ if (locale != null) {
+ this.locale = locale;
+ } else {
+ // TODO: set default
+ }
+ }
+
+ public String getHeaderString() {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append("xid=" + xid);
+ buffer.append(", locale=" + locale);
+ return buffer.toString();
+ }
+
+ public abstract String toString();
+
+ /**
+ *
+ * @return
+ */
+ public abstract int getSize();
+
+ int getHeaderSize() {
+ return 14 + locale.getLanguage().length();
+ }
+
+
+ protected static String arrayToString(final String[] arr, final String delim) {
+ return SLPUtils.arrayToString(arr, delim);
+ }
+
+ protected static List<String> stringToList(final String str, final String delim) {
+ return SLPUtils.stringToList(str, delim);
+ }
+
+ protected static List<String> arrayToList(final String[] arr){
+ return SLPUtils.arrayToList(arr);
+ }
+
+
+
+
+
+
+ /**
+ * get the bytes from a SLPMessage. Processes the header and then calls the
+ * getBody() method of the implementing subclass.
+ *
+ * @return an array of bytes encoding the SLPMessage.
+ * @throws IOException
+ * @throws ServiceLocationException
+ * in case of IOExceptions.
+ */
+ protected void writeHeader(final DataOutputStream out, int msgSize, int mtu)
+ throws IOException {
+ byte flags = 0;
+ if (funcID == SRVREG) {
+ flags |= 0x40;
+ }
+ if (multicast) {
+ flags |= 0x20;
+ }
+ if (!tcp && msgSize > mtu) {
+ flags |= 0x80;
+ }
+ out.write(2);
+ out.write(funcID);
+ out.write((byte) ((msgSize) >> 16));
+ out.write((byte) (((msgSize) >> 8) & 0xFF));
+ out.write((byte) ((msgSize) & 0xFF));
+ out.write(flags);
+ out.write(0);
+ out.write(0);
+ out.write(0);
+ out.write(0);
+ out.writeShort(xid);
+ out.writeUTF(locale.getLanguage());
+ }
+
+ public abstract void writeTo(final DataOutputStream out, final int mtu) throws IOException;
+
+ public String getSource(){
+ return source;
+ }
+
+ public void setSource(String s){
+ source=s;
+ }
+
+ public int getPort(){
+ return port;
+ }
+
+ public void setPort(int p){
+ port=p;
+ }
+
+
+
+ /**
+ * Return the String corresponding to the FuncID
+ *
+ * @param funcID the message type as int
+ * @return The String representation of that type
+ */
+ public static String getType(int funcID){
+ return TYPES[funcID];
+ }
+
+
+ public AbstractExtension[] getExtensions(){
+ return extensions;
+ }
+
+ public void setExtensions(AbstractExtension[] extensions){
+ this.extensions = extensions;
+ }
+
+ public void addExtension(AbstractExtension extension){
+ AbstractExtension[] newExt = new AbstractExtension[extensions.length+1];
+ int i = 0;
+ for (AbstractExtension ae : extensions){
+ newExt[i++]=ae;
+ }
+ newExt[i] = extension;
+ extensions = newExt;
+ }
+
+ public boolean hasExtensions(){
+ if (extensions == null){
+ return false;
+ }
+ return (extensions.length>0);
+ }
+
+ public boolean hasExtensionType(short id){
+ for (AbstractExtension ae : extensions){
+ if (ae.getId()==id){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasUnsupportedExtensions(){
+ for (AbstractExtension ae : extensions){
+ if (ae instanceof UnsupportedExtension){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasUnsupportedMandatoryExtensions(){
+ for (AbstractExtension ae : extensions){
+ if (ae instanceof UnsupportedExtension){
+ if (ae.isMandatory()){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
+
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPMessage.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPReplyMessage.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPReplyMessage.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPReplyMessage.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPReplyMessage.java Tue Jun 9 12:00:29 2009
@@ -0,0 +1,75 @@
+/*
+ * 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.directory.slp.messages;
+
+import java.util.List;
+
+/**
+ * abstract base class for all ReplyMessages.
+ *
+ * @author Jan S. Rellermeyer
+ */
+public abstract class AbstractSLPReplyMessage extends AbstractSLPMessage {
+
+ /**
+ * the error code that is returned.
+ */
+ private short errorCode;
+
+ AbstractSLPReplyMessage(byte funcID) {
+ super(funcID);
+ }
+
+ public void setErrorCode(final short errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public short getErrorCode() {
+ return errorCode;
+ }
+
+ public final String getHeaderString() {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append(super.getHeaderString());
+ buffer.append(", errorCode=");
+ buffer.append(errorCode);
+ return buffer.toString();
+ }
+
+
+ /**
+ * get the results.
+ *
+ * @return the Array of results.
+ */
+ public abstract String[] getResult();
+
+ /**
+ * get the results.
+ *
+ * @return the List of results.
+ */
+ public abstract List<String> getResultAsList();
+
+
+
+
+
+}
Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/messages/AbstractSLPReplyMessage.java
------------------------------------------------------------------------------
svn:mime-type = text/plain