📄 service.java
字号:
// 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-2009, 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.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
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.crypto.KeyManager;
import org.smslib.helper.Logger;
import org.smslib.routing.Router;
import org.smslib.scheduler.ASchedulerTask;
import org.smslib.scheduler.Scheduler;
/**
* This is main library class. Your primary interface with SMSLib is via methods
* defined in this class.
*/
public class Service
{
public enum ServiceStatus
{
STARTED, STOPPED
}
private Logger logger;
private List<AGateway> gatewayList;
private Router router;
private LoadBalancer loadBalancer;
private WatchDog watchDog;
private Scheduler scheduler;
private IInboundMessageNotification inboundNotification;
private IOutboundMessageNotification outboundNotification;
private ICallNotification callNotification;
private IGatewayStatusNotification gatewayStatusNotification;
private IQueueSendingNotification queueSendingNotification;
protected QueueManager queueManager;
private long startMillis;
private Collection<Group> groups;
private volatile ServiceStatus serviceStatus;
private KeyManager keyManager;
/**
* Configuration settings.
*
* @see Settings
*/
private Settings S;
/**
* Default Service constructor. Will set SMSLib to use its own logger.
*/
public Service()
{
setSettings(new Settings());
logger = new Logger(getSettings());
initializeService();
}
/**
* Service constructor. Will set SMSLib to use the provided log4j logger.
*
* @param myLogger
* A ready Apache log4j object to use.
*/
public Service(org.slf4j.Logger myLogger)
{
setSettings(new Settings());
logger = new Logger(myLogger);
initializeService();
}
protected void initializeService()
{
startMillis = System.currentTimeMillis();
setServiceStatus(ServiceStatus.STOPPED);
groups = new ArrayList<Group>();
listSystemInformation();
gatewayList = new ArrayList<AGateway>();
keyManager = KeyManager.getInstance();
setRouter(new Router(this));
setLoadBalancer(new RoundRobinLoadBalancer(this));
setWatchDog(new WatchDog("WatchDog", this));
setQueueManager(new QueueManager(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 logger;
}
/**
* Adds a gateway to the list of gateways managed by the Service class. The
* Service should be stopped in order to add gateways.
*
* @param gateway
* The gateway to be added.
* @throws GatewayException
* You tried to add a gateway while the Service is started.
* @see #getGateways()
*/
public void addGateway(AGateway gateway) throws GatewayException
{
if (getServiceStatus() == ServiceStatus.STARTED) throw new GatewayException("Cannot add gateway while Service is running!");
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
{
setServiceStatus(ServiceStatus.STARTED);
scheduler = new Scheduler(this, getLogger(), getGateways().size() * 5);
getScheduler().scheduleAtFixedRate(getWatchDog(), getSettings().WATCHDOG_INTERVAL, getSettings().WATCHDOG_INTERVAL, TimeUnit.SECONDS);
getWatchDog().enable();
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 gateway, List<ExceptionPair> eList, List<AGateway> gList)
{
this.gateway = gateway;
this.eList = eList;
this.gList = gList;
}
@Override
public void run()
{
try
{
gateway.startGateway();
gList.add(gateway);
}
catch (Exception e)
{
ExceptionPair exc = new ExceptionPair();
exc.e = e;
exc.src = gateway;
eList.add(exc);
}
}
}
if (getSettings().CONCURRENT_GATEWAY_START)
{
List<ExceptionPair> eList;
List<AGateway> gList;
eList = new LinkedList<ExceptionPair>();
gList = new LinkedList<AGateway>();
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.setStatus(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;
if (e.e instanceof SMSLibException) throw (SMSLibException) e.e;
if (e.e instanceof IOException) throw (IOException) e.e;
if (e.e instanceof InterruptedException) throw (InterruptedException) e.e;
}
else
{
eList.clear();
gList.clear();
}
}
}
else
{
if (getGateways().size() == 0) throw new SMSLibException("No gateways are defined.");
for (AGateway gateway : getGateways())
gateway.startGateway();
}
}
/**
* Stops all gateways - does not remove them from Service's internal list.
* Once stopped, all SMSLib operations will fail. You need to start the
* gateways again before proceeding.
*
* @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 #startService()
*/
public synchronized void stopService() throws TimeoutException, GatewayException, IOException, InterruptedException
{
setServiceStatus(ServiceStatus.STOPPED);
if (getScheduler() != null)
{
if (getWatchDog() != null) getScheduler().remove(getWatchDog());
}
for (AGateway gateway : getGateways())
gateway.stopGateway();
if (getScheduler() != null) getScheduler().shutdown();
}
/**
* Reads inbound messages from ALL gateways with the Inbound attribute set.
* When successful, the message list will contain all messages read.
*
* @param msgList
* A (probably empty) list that will be populated with Inbound
* messages read.
* @param msgClass
* Filtering: Class of messages that need to be read.
* @return The number of messages read.
* @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 MessageClasses
*/
public int readMessages(Collection<InboundMessage> msgList, MessageClasses msgClass) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getServiceStatus() == ServiceStatus.STOPPED) return 0;
for (AGateway gateway : getGateways())
{
if (gateway.isInbound())
{
try
{
readMessages(msgList, msgClass, gateway);
}
catch (TimeoutException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " does not respond, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
catch (IOException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " throws IO errors, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
}
}
return msgList.size();
}
/**
* .NET bridge method.
*/
public InboundMessage[] readMessages(MessageClasses msgClass) throws TimeoutException, GatewayException, IOException, InterruptedException
{
ArrayList<InboundMessage> messageList = new ArrayList<InboundMessage>();
readMessages(messageList, msgClass);
return messageList.toArray(new InboundMessage[0]);
}
/**
* Reads inbound messages from the SPECIFIC gateway. When successful, the
* message list will contain all messages read.
*
* @param msgList
* A (probably empty) list that will be populated with Inbound
* messages read.
* @param msgClass
* Filtering: Class of messages that need to be read.
* @param gatewayId
* The identifier of the gateway from which to read messages.
* @return The number of messages read.
* @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 MessageClasses
* @see AGateway
*/
public int readMessages(Collection<InboundMessage> msgList, MessageClasses msgClass, String gatewayId) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getServiceStatus() == ServiceStatus.STOPPED) return 0;
AGateway gateway = findGateway(gatewayId);
if ((gateway != null) && (gateway.isInbound()))
{
try
{
readMessages(msgList, msgClass, gateway);
}
catch (TimeoutException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " does not respond, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
catch (IOException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " throws IO errors, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
}
return msgList.size();
}
/**
* .NET bridge method.
*/
public InboundMessage[] readMessages(MessageClasses msgClass, String gatewayId) throws TimeoutException, GatewayException, IOException, InterruptedException
{
ArrayList<InboundMessage> messageList = new ArrayList<InboundMessage>();
readMessages(messageList, msgClass, gatewayId);
return messageList.toArray(new InboundMessage[0]);
}
/**
* Reads inbound messages from the SPECIFIC gateway. When successful, the
* message list will contain all messages read.
*
* @param msgList
* A (probably empty) list that will be populated with inbound
* messages read.
* @param msgClass
* Filtering: Class of messages that need to be read.
* @param gateway
* The gateway object from which to read messages.
* @return The number of messages read.
* @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 MessageClasses
* @see AGateway
*/
public int readMessages(Collection<InboundMessage> msgList, MessageClasses msgClass, AGateway gateway) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getServiceStatus() == ServiceStatus.STOPPED) return 0;
try
{
gateway.readMessages(msgList, msgClass);
}
catch (TimeoutException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " does not respond, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
catch (IOException e)
{
getLogger().logWarn("readMessages(): Gateway " + gateway.getGatewayId() + " throws IO errors, marking for restart.", null, null);
gateway.setStatus(GatewayStatuses.RESTART);
}
return msgList.size();
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -