// SMSLib for Java v3
// A Java API library for sending and receiving SMS via a GSM modem
// or other supported gateways.
// Web Site: http://www.smslib.org
//
// Copyright (C) 2002-2008, Thanasis Delenikas, Athens/GREECE.
// SMSLib is distributed under the terms of the Apache License version 2.0
//
// 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.
package org.smslib;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import org.smslib.AGateway.GatewayStatuses;
import org.smslib.InboundMessage.MessageClasses;
import org.smslib.OutboundMessage.FailureCauses;
import org.smslib.OutboundMessage.MessageStatuses;
import org.smslib.balancing.LoadBalancer;
import org.smslib.balancing.RoundRobinLoadBalancer;
import org.smslib.helper.Logger;
import org.smslib.routing.Router;
/**
* This is main library class. Your primary interface with SMSLib is via methods
* defined in this class.
*/
public class Service
{
private Logger logger;
private List<AGateway> gatewayList;
private Router router;
private LoadBalancer loadBalancer;
private WatchDog watchDog;
private IInboundMessageNotification inboundNotification;
private IOutboundMessageNotification outboundNotification;
private ICallNotification callNotification;
private IGatewayStatusNotification gatewayStatusNotification;
private Queue<OutboundMessage> reorderMessageQueue;
/**
* Configuration settings.
*
* @see Settings
*/
public Settings S;
/**
* Default Service constructor. Will set SMSLib to use its own logger.
*/
public Service()
{
this.S = new Settings();
this.logger = new Logger(this.S);
listSystemInformation();
this.gatewayList = new ArrayList<AGateway>();
this.reorderMessageQueue = new PriorityQueue<OutboundMessage>(50, new Comparator<OutboundMessage>()
{
public int compare(OutboundMessage x, OutboundMessage y)
{
int comp = x.getPriority() - y.getPriority();
if (comp == 0) comp = x.getDate().compareTo(y.getDate());
return comp;
}
});
setRouter(new Router(this));
setLoadBalancer(new RoundRobinLoadBalancer(this));
}
/**
* Service constructor. Will set SMSLib to use the provided log4j logger.
*
* @param myLogger
* A ready log4j logger to use.
*/
public Service(Logger myLogger)
{
this.S = new Settings();
this.logger = new Logger(this.S);
listSystemInformation();
this.gatewayList = new ArrayList<AGateway>();
this.reorderMessageQueue = new PriorityQueue<OutboundMessage>(50, new Comparator<OutboundMessage>()
{
public int compare(OutboundMessage x, OutboundMessage y)
{
int comp = x.getPriority() - y.getPriority();
if (comp == 0) comp = x.getDate().compareTo(y.getDate());
return comp;
}
});
setRouter(new Router(this));
setLoadBalancer(new RoundRobinLoadBalancer(this));
}
private void listSystemInformation()
{
getLogger().logInfo(Library.getLibraryDescription(), null, null);
getLogger().logInfo("Version: " + Library.getLibraryVersion(), null, null);
getLogger().logInfo("JRE Version: " + System.getProperty("java.version"), null, null);
getLogger().logInfo("JRE Impl Version: " + System.getProperty("java.vm.version"), null, null);
getLogger().logInfo("O/S: " + System.getProperty("os.name") + " / " + System.getProperty("os.arch") + " / " + System.getProperty("os.version"), null, null);
}
/**
* Returns the logger used by SMSLib.
*
* @return The logger in use.
*/
public Logger getLogger()
{
return this.logger;
}
/**
* Adds a gateway to the list of gateways managed by the Service class.
*
* @param gateway
* The gateway to be added.
* @see #getGateways()
*/
public void addGateway(AGateway gateway)
{
synchronized (getGateways())
{
gateway.setService(this);
getGateways().add(gateway);
}
}
/**
* Initializes all gateways. This should be the first call before you use
* the Service class for sending/receiving messages. The call will try to
* start all defined gateways.
*
* @throws SMSLibException
* No Gateways are defined.
* @throws TimeoutException
* The gateway did not respond in a timely manner.
* @throws GatewayException
* A Gateway error occurred.
* @throws IOException
* An IO error occurred.
* @throws InterruptedException
* The call was interrupted.
* @see #stopService()
*/
public synchronized void startService() throws SMSLibException, TimeoutException, GatewayException, IOException, InterruptedException
{
startService(true);
}
/**
* Initializes all gateways. This should be the first call before you use
* the Service class for sending/receiving messages. The call will try to
* start all or some of the defined gateways, depending on the parameter.
*
* @param startAll
* True if it is imperative that all defined gateways start
* without errors. False if some gateways are allowed to fail
* during startup.
* @throws SMSLibException
* No Gateways are defined.
* @throws TimeoutException
* The gateway did not respond in a timely manner.
* @throws GatewayException
* A Gateway error occurred.
* @throws IOException
* An IO error occurred.
* @throws InterruptedException
* The call was interrupted.
* @see #stopService()
*/
public synchronized void startService(boolean startAll) throws SMSLibException, TimeoutException, GatewayException, IOException, InterruptedException
{
class ExceptionPair
{
public Throwable e;
public AGateway src;
}
class Starter extends Thread
{
AGateway gateway;
List<ExceptionPair> eList;
List<AGateway> gList;
public Starter(AGateway myGateway, List<ExceptionPair> myEList, List<AGateway> myGList)
{
this.gateway = myGateway;
this.eList = myEList;
this.gList = myGList;
}
@Override
public void run()
{
try
{
this.gateway.startGateway();
this.gList.add(this.gateway);
}
catch (Exception e)
{
ExceptionPair exc = new ExceptionPair();
exc.e = e;
exc.src = this.gateway;
this.eList.add(exc);
}
}
}
this.watchDog = new WatchDog();
if (this.S.CONCURRENT_GATEWAY_START)
{
List<ExceptionPair> eList;
List<AGateway> gList;
eList = new LinkedList<ExceptionPair>();
gList = new LinkedList<AGateway>();
synchronized (getGateways())
{
if (getGateways().size() == 0) throw new SMSLibException("No gateways are defined.");
for (AGateway gateway : getGateways())
new Starter(gateway, eList, gList).start();
while ((gList.size() != getGateways().size()) && (eList.size() == 0))
Thread.sleep(1000);
for (ExceptionPair e : eList)
e.src.setGatewayStatus(GatewayStatuses.RESTART);
if (startAll)
{
if (eList.size() != 0)
{
ExceptionPair e = eList.get(0);
if (e.e instanceof TimeoutException) throw (TimeoutException) e.e;
if (e.e instanceof GatewayException) throw (GatewayException) e.e;