PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/examples/charging-server-simulator/src/main/java/org/mobicents/servers/diameter/charging/ChargingServerSimulator.java

http://mobicents.googlecode.com/
Java | 572 lines | 281 code | 68 blank | 223 comment | 42 complexity | 7504616aeeed7de8cc97c574211b8db7 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. package org.mobicents.servers.diameter.charging;
  2. import java.io.BufferedInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.util.HashMap;
  6. import java.util.Properties;
  7. import java.util.concurrent.TimeUnit;
  8. import org.jdiameter.api.Answer;
  9. import org.jdiameter.api.ApplicationId;
  10. import org.jdiameter.api.Avp;
  11. import org.jdiameter.api.AvpDataException;
  12. import org.jdiameter.api.AvpSet;
  13. import org.jdiameter.api.EventListener;
  14. import org.jdiameter.api.InternalException;
  15. import org.jdiameter.api.Mode;
  16. import org.jdiameter.api.Network;
  17. import org.jdiameter.api.NetworkReqListener;
  18. import org.jdiameter.api.Peer;
  19. import org.jdiameter.api.Request;
  20. import org.jdiameter.api.app.AppAnswerEvent;
  21. import org.jdiameter.api.app.AppRequestEvent;
  22. import org.jdiameter.api.app.AppSession;
  23. import org.jdiameter.api.auth.events.ReAuthAnswer;
  24. import org.jdiameter.api.auth.events.ReAuthRequest;
  25. import org.jdiameter.api.cca.ClientCCASession;
  26. import org.jdiameter.api.cca.ServerCCASession;
  27. import org.jdiameter.api.cca.events.JCreditControlAnswer;
  28. import org.jdiameter.api.cca.events.JCreditControlRequest;
  29. import org.jdiameter.client.api.ISessionFactory;
  30. import org.jdiameter.common.impl.app.cca.CCASessionFactoryImpl;
  31. import org.jdiameter.common.impl.app.cca.JCreditControlAnswerImpl;
  32. import org.jdiameter.server.impl.app.cca.ServerCCASessionImpl;
  33. import org.mobicents.diameter.dictionary.AvpDictionary;
  34. import org.mobicents.servers.diameter.utils.DiameterUtilities;
  35. import org.mobicents.servers.diameter.utils.StackCreator;
  36. import org.slf4j.Logger;
  37. import org.slf4j.LoggerFactory;
  38. /**
  39. * Mobicents Diameter Charging Server Simulator.
  40. *
  41. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  42. */
  43. public class ChargingServerSimulator extends CCASessionFactoryImpl implements NetworkReqListener, EventListener<Request, Answer> {
  44. private static final Logger logger = LoggerFactory.getLogger(ChargingServerSimulator.class);
  45. private static final Object[] EMPTY_ARRAY = new Object[]{};
  46. private ApplicationId roAppId = ApplicationId.createByAuthAppId(10415L, 4L);
  47. private HashMap<String, Long> accounts = new HashMap<String, Long>();
  48. private HashMap<String, Long> reserved = new HashMap<String, Long>();
  49. /**
  50. * @param args
  51. * @throws Exception
  52. */
  53. public static void main(String[] args) throws Exception {
  54. new ChargingServerSimulator();
  55. }
  56. StackCreator stackCreator = null;
  57. public ChargingServerSimulator() throws Exception {
  58. super();
  59. AvpDictionary.INSTANCE.parseDictionary(this.getClass().getClassLoader().getResourceAsStream("dictionary.xml"));
  60. try {
  61. String config = readFile(this.getClass().getClassLoader().getResourceAsStream("config-server.xml"));
  62. this.stackCreator = new StackCreator(config, this, this, "Server", true);
  63. Network network = this.stackCreator.unwrap(Network.class);
  64. network.addNetworkReqListener(this, roAppId);
  65. network.addNetworkReqListener(this, ApplicationId.createByAuthAppId(0, 4));
  66. this.stackCreator.start(Mode.ALL_PEERS, 30000, TimeUnit.MILLISECONDS);
  67. printLogo();
  68. sessionFactory = (ISessionFactory) stackCreator.getSessionFactory();
  69. init(sessionFactory); // damn.. this doesn't looks good
  70. ((ISessionFactory) sessionFactory).registerAppFacory(ServerCCASession.class, this);
  71. ((ISessionFactory) sessionFactory).registerAppFacory(ClientCCASession.class, this);
  72. // Read users from properties file
  73. Properties properties = new Properties();
  74. try {
  75. InputStream is = this.getClass().getClassLoader().getResourceAsStream("accounts.properties");
  76. if(is == null) {
  77. throw new IOException("InputStream is null");
  78. }
  79. properties.load(is);
  80. for(Object property : properties.keySet()) {
  81. String accountName = (String) property;
  82. String balance = (String) properties.getProperty(accountName, "0");
  83. if(logger.isInfoEnabled()) {
  84. logger.info("Provisioned user '" + accountName + "' with [" + balance + "] units.");
  85. }
  86. accounts.put(accountName, Long.valueOf(balance));
  87. }
  88. }
  89. catch (IOException e) {
  90. System.err.println("Failed to read 'accounts.properties' file. Aborting.");
  91. System.exit(-1);
  92. }
  93. }
  94. catch (Exception e) {
  95. logger.error("Failure initializing Mobicents Diameter Ro/Rf Server Simulator", e);
  96. }
  97. }
  98. private void printLogo() {
  99. if(logger.isInfoEnabled()) {
  100. Properties sysProps = System.getProperties();
  101. String osLine = sysProps.getProperty("os.name") + "/" + sysProps.getProperty("os.arch");
  102. String javaLine = sysProps.getProperty("java.vm.vendor") + " " + sysProps.getProperty("java.vm.name") + " " + sysProps.getProperty("java.vm.version");
  103. Peer localPeer = stackCreator.getMetaData().getLocalPeer();
  104. String diameterLine = localPeer.getProductName() + " (" + localPeer.getUri() + " @ " + localPeer.getRealmName() + ")";
  105. logger.info("===============================================================================");
  106. logger.info("");
  107. logger.info("== Mobicents Diameter Ro/Rf Server Simulator (" + osLine + ")" );
  108. logger.info("");
  109. logger.info("== " + javaLine);
  110. logger.info("");
  111. logger.info("== " + diameterLine);
  112. logger.info("");
  113. logger.info("===============================================================================");
  114. }
  115. }
  116. public Answer processRequest(Request request) {
  117. if(logger.isInfoEnabled()) {
  118. logger.info("<< Received Request [" + request + "]");
  119. }
  120. try {
  121. ServerCCASessionImpl session = (sessionFactory).getNewAppSession(request.getSessionId(), ApplicationId.createByAuthAppId(0, 4), ServerCCASession.class, EMPTY_ARRAY);
  122. session.processRequest(request);
  123. }
  124. catch (InternalException e) {
  125. logger.error(">< Failure handling received request.", e);
  126. }
  127. return null;
  128. }
  129. public void receivedSuccessMessage(Request request, Answer answer) {
  130. if(logger.isInfoEnabled()) {
  131. logger.info("<< Received Success Message for Request [" + request + "] and Answer [" + answer + "]");
  132. }
  133. }
  134. @Override
  135. public void timeoutExpired(Request request) {
  136. if(logger.isInfoEnabled()) {
  137. logger.info("<< Received Timeout for Request [" + request + "]");
  138. }
  139. }
  140. public void doCreditControlAnswer(ClientCCASession session, JCreditControlRequest request, JCreditControlAnswer answer) throws InternalException {
  141. // Do nothing.
  142. }
  143. public void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer) throws InternalException {
  144. // Do nothing.
  145. }
  146. public void doReAuthRequest(ClientCCASession session, ReAuthRequest request) throws InternalException {
  147. // Do nothing.
  148. }
  149. @Override
  150. public void doCreditControlRequest(ServerCCASession session, JCreditControlRequest request) throws InternalException {
  151. AvpSet ccrAvps = request.getMessage().getAvps();
  152. switch (request.getRequestTypeAVPValue()) {
  153. // INITIAL_REQUEST 1
  154. case 1:
  155. // UPDATE_REQUEST 2
  156. case 2:
  157. if(logger.isInfoEnabled()) {
  158. logger.info("<< Received Credit-Control-Request [" + (request.getRequestTypeAVPValue() == 1 ? "INITIAL" : "UPDATE") + "]");
  159. }
  160. JCreditControlAnswer cca = null;
  161. try {
  162. long requestedUnits = ccrAvps.getAvp(437).getGrouped().getAvp(420).getInteger32();
  163. String subscriptionId = ccrAvps.getAvp(443).getGrouped().getAvp(444).getUTF8String();
  164. String serviceContextId = ccrAvps.getAvp(461).getUTF8String();
  165. if(logger.isInfoEnabled()) {
  166. logger.info(">> '" + subscriptionId + "' requested " + requestedUnits + " units for '" + serviceContextId + "'.");
  167. }
  168. Long balance = accounts.get(subscriptionId);
  169. if(balance != null) {
  170. if(balance <= 0) {
  171. // DIAMETER_CREDIT_LIMIT_REACHED 4012
  172. // The credit-control server denies the service request because the
  173. // end user's account could not cover the requested service. If the
  174. // CCR contained used-service-units they are deducted, if possible.
  175. cca = createCCA(session, request, -1, 4012);
  176. if(logger.isInfoEnabled()) {
  177. logger.info("<> '" + subscriptionId + "' has insufficient credit units. Rejecting.");
  178. }
  179. }
  180. else {
  181. // Check if not first request, should have Used-Service-Unit AVP
  182. if(ccrAvps.getAvp(415) != null && ccrAvps.getAvp(415).getUnsigned32() >= 1) {
  183. Avp usedServiceUnit = ccrAvps.getAvp(446);
  184. if(usedServiceUnit != null) {
  185. Long wereReserved = reserved.remove(subscriptionId + "_" + serviceContextId);
  186. wereReserved = wereReserved == null ? 0 : wereReserved;
  187. long wereUsed = usedServiceUnit.getGrouped().getAvp(420).getUnsigned32();
  188. long remaining = wereReserved - wereUsed;
  189. if(logger.isInfoEnabled()) {
  190. logger.info(">> '" + subscriptionId + "' had " + wereReserved + " reserved units, " + wereUsed + " units were used. (rem: " + remaining + ").");
  191. }
  192. balance += remaining;
  193. }
  194. }
  195. long grantedUnits = Math.min(requestedUnits, balance);
  196. cca = createCCA(session, request, grantedUnits, 2001);
  197. reserved.put(subscriptionId + "_" + serviceContextId, grantedUnits);
  198. balance -= grantedUnits;
  199. if(logger.isInfoEnabled()) {
  200. logger.info(">> '" + subscriptionId + "' Balance: " + (balance + grantedUnits) + " // Available(" + balance + ") Reserved(" + grantedUnits + ")");
  201. }
  202. accounts.put(subscriptionId, balance);
  203. // Check if the user has no more credit
  204. if(balance <= 0) {
  205. // 8.34. Final-Unit-Indication AVP
  206. //
  207. // The Final-Unit-Indication AVP (AVP Code 430) is of type Grouped and
  208. // indicates that the Granted-Service-Unit AVP in the Credit-Control-
  209. // Answer, or in the AA answer, contains the final units for the
  210. // service. After these units have expired, the Diameter credit-control
  211. // client is responsible for executing the action indicated in the
  212. // Final-Unit-Action AVP (see section 5.6).
  213. //
  214. // If more than one unit type is received in the Credit-Control-Answer,
  215. // the unit type that first expired SHOULD cause the credit-control
  216. // client to execute the specified action.
  217. //
  218. // In the first interrogation, the Final-Unit-Indication AVP with
  219. // Final-Unit-Action REDIRECT or RESTRICT_ACCESS can also be present
  220. // with no Granted-Service-Unit AVP in the Credit-Control-Answer or in
  221. // the AA answer. This indicates to the Diameter credit-control client
  222. // to execute the specified action immediately. If the home service
  223. // provider policy is to terminate the service, naturally, the server
  224. // SHOULD return the appropriate transient failure (see section 9.1) in
  225. // order to implement the policy-defined action.
  226. //
  227. // The Final-Unit-Action AVP defines the behavior of the service element
  228. // when the user's account cannot cover the cost of the service and MUST
  229. // always be present if the Final-Unit-Indication AVP is included in a
  230. // command.
  231. //
  232. // If the Final-Unit-Action AVP is set to TERMINATE, no other AVPs MUST
  233. // be present.
  234. //
  235. // If the Final-Unit-Action AVP is set to REDIRECT at least the
  236. // Redirect-Server AVP MUST be present. The Restriction-Filter-Rule AVP
  237. // or the Filter-Id AVP MAY be present in the Credit-Control-Answer
  238. // message if the user is also allowed to access other services that are
  239. // not accessible through the address given in the Redirect-Server AVP.
  240. //
  241. // If the Final-Unit-Action AVP is set to RESTRICT_ACCESS, either the
  242. // Restriction-Filter-Rule AVP or the Filter-Id AVP SHOULD be present.
  243. //
  244. // The Filter-Id AVP is defined in [NASREQ]. The Filter-Id AVP can be
  245. // used to reference an IP filter list installed in the access device by
  246. // means other than the Diameter credit-control application, e.g.,
  247. // locally configured or configured by another entity.
  248. //
  249. // The Final-Unit-Indication AVP is defined as follows (per the
  250. // grouped-avp-def of RFC 3588 [DIAMBASE]):
  251. //
  252. // Final-Unit-Indication ::= < AVP Header: 430 >
  253. // { Final-Unit-Action }
  254. // *[ Restriction-Filter-Rule ]
  255. // *[ Filter-Id ]
  256. // [ Redirect-Server ]
  257. AvpSet finalUnitIndicationAvp = cca.getMessage().getAvps().addGroupedAvp(430);
  258. // 8.35. Final-Unit-Action AVP
  259. //
  260. // The Final-Unit-Action AVP (AVP Code 449) is of type Enumerated and
  261. // indicates to the credit-control client the action to be taken when
  262. // the user's account cannot cover the service cost.
  263. //
  264. // The Final-Unit-Action can be one of the following:
  265. //
  266. // TERMINATE 0
  267. // The credit-control client MUST terminate the service session.
  268. // This is the default handling, applicable whenever the credit-
  269. // control client receives an unsupported Final-Unit-Action value,
  270. // and it MUST be supported by all the Diameter credit-control client
  271. // implementations conforming to this specification.
  272. //
  273. // REDIRECT 1
  274. // The service element MUST redirect the user to the address
  275. // specified in the Redirect-Server-Address AVP. The redirect action
  276. // is defined in section 5.6.2.
  277. //
  278. // RESTRICT_ACCESS 2
  279. // The access device MUST restrict the user access according to the
  280. // IP packet filters defined in the Restriction-Filter-Rule AVP or
  281. // according to the IP packet filters identified by the Filter-Id
  282. // AVP. All the packets not matching the filters MUST be dropped
  283. // (see section 5.6.3).
  284. finalUnitIndicationAvp.addAvp(449, 0);
  285. }
  286. }
  287. }
  288. else {
  289. // DIAMETER_USER_UNKNOWN 5030
  290. // The specified end user is unknown in the credit-control server.
  291. cca = createCCA(session, request, -1, 5030);
  292. cca.getMessage().setError(true);
  293. if(logger.isInfoEnabled()) {
  294. logger.info("<> '" + subscriptionId + "' is not provisioned in this server. Rejecting.");
  295. }
  296. }
  297. //cca.getMessage().getAvps().addAvp(461, serviceContextId, false);
  298. session.sendCreditControlAnswer(cca);
  299. }
  300. catch (Exception e) {
  301. logger.error(">< Failure processing Credit-Control-Request [" + (request.getRequestTypeAVPValue() == 1 ? "INITIAL" : "UPDATE") + "]", e);
  302. }
  303. break;
  304. // TERMINATION_REQUEST 3
  305. case 3:
  306. if(logger.isInfoEnabled()) {
  307. logger.info("<< Received Credit-Control-Request [TERMINATION]");
  308. }
  309. try {
  310. String subscriptionId = ccrAvps.getAvp(443).getGrouped().getAvp(444).getUTF8String();
  311. String serviceContextId = ccrAvps.getAvp(461).getUTF8String();
  312. if(logger.isInfoEnabled()) {
  313. logger.info(">> '" + subscriptionId + "' requested service termination for '" + serviceContextId + "'.");
  314. }
  315. Long balance = accounts.get(subscriptionId);
  316. if(ccrAvps.getAvp(415) != null && ccrAvps.getAvp(415).getUnsigned32() >= 1) {
  317. Avp usedServiceUnit = ccrAvps.getAvp(446);
  318. if(usedServiceUnit != null) {
  319. long wereReserved = reserved.remove(subscriptionId + "_" + serviceContextId);
  320. long wereUsed = usedServiceUnit.getGrouped().getAvp(420).getUnsigned32();
  321. long remaining = wereReserved - wereUsed;
  322. if(logger.isInfoEnabled()) {
  323. logger.info(">> '" + subscriptionId + "' had " + wereReserved + " reserved units, " + wereUsed + " units were used. (non-used: " + remaining + ").");
  324. }
  325. balance += remaining;
  326. }
  327. }
  328. if(logger.isInfoEnabled()) {
  329. logger.info(">> '" + subscriptionId + "' Balance: " + balance + " // Available(" + balance + ") Reserved(0)");
  330. }
  331. accounts.put(subscriptionId, balance);
  332. cca = createCCA(session, request, -1, 2001);
  333. // 8.7. Cost-Information AVP
  334. //
  335. // The Cost-Information AVP (AVP Code 423) is of type Grouped, and it is
  336. // used to return the cost information of a service, which the credit-
  337. // control client can transfer transparently to the end user. The
  338. // included Unit-Value AVP contains the cost estimate (always type of
  339. // money) of the service, in the case of price enquiry, or the
  340. // accumulated cost estimation, in the case of credit-control session.
  341. //
  342. // The Currency-Code specifies in which currency the cost was given.
  343. // The Cost-Unit specifies the unit when the service cost is a cost per
  344. // unit (e.g., cost for the service is $1 per minute).
  345. //
  346. // When the Requested-Action AVP with value PRICE_ENQUIRY is included in
  347. // the Credit-Control-Request command, the Cost-Information AVP sent in
  348. // the succeeding Credit-Control-Answer command contains the cost
  349. // estimation of the requested service, without any reservation being
  350. // made.
  351. //
  352. // The Cost-Information AVP included in the Credit-Control-Answer
  353. // command with the CC-Request-Type set to UPDATE_REQUEST contains the
  354. // accumulated cost estimation for the session, without taking any
  355. // credit reservation into account.
  356. //
  357. // The Cost-Information AVP included in the Credit-Control-Answer
  358. // command with the CC-Request-Type set to EVENT_REQUEST or
  359. // TERMINATION_REQUEST contains the estimated total cost for the
  360. // requested service.
  361. //
  362. // It is defined as follows (per the grouped-avp-def of
  363. // RFC 3588 [DIAMBASE]):
  364. //
  365. // Cost-Information ::= < AVP Header: 423 >
  366. // { Unit-Value }
  367. // { Currency-Code }
  368. // [ Cost-Unit ]
  369. // 7.2.133 Remaining-Balance AVP
  370. //
  371. // The Remaining-Balance AVP (AVPcode 2021) is of type Grouped and
  372. // provides information about the remaining account balance of the
  373. // subscriber.
  374. //
  375. // It has the following ABNF grammar:
  376. // Remaining-Balance :: = < AVP Header: 2021 >
  377. // { Unit-Value }
  378. // { Currency-Code }
  379. // We use no money notion ... maybe later.
  380. // AvpSet costInformation = ccaAvps.addGroupedAvp(423);
  381. session.sendCreditControlAnswer(cca);
  382. }
  383. catch (Exception e) {
  384. logger.error(">< Failure processing Credit-Control-Request [TERMINATION]", e);
  385. }
  386. break;
  387. // EVENT_REQUEST 4
  388. case 4:
  389. if (logger.isInfoEnabled()) {
  390. logger.info("<< Received Credit-Control-Request [EVENT]");
  391. }
  392. break;
  393. default:
  394. break;
  395. }
  396. }
  397. public void doReAuthAnswer(ServerCCASession session, ReAuthRequest request, ReAuthAnswer answer) throws InternalException {
  398. // Do Nothing.
  399. }
  400. public void sessionSupervisionTimerExpired(ServerCCASession session) {
  401. // Do Nothing.
  402. }
  403. public void denyAccessOnTxExpire(ClientCCASession clientCCASessionImpl) {
  404. // Do Nothing.
  405. }
  406. public void txTimerExpired(ClientCCASession session) {
  407. // Do Nothing.
  408. }
  409. private JCreditControlAnswer createCCA(ServerCCASession session, JCreditControlRequest request, long grantedUnits, long resultCode) throws InternalException, AvpDataException {
  410. JCreditControlAnswerImpl answer = new JCreditControlAnswerImpl((Request) request.getMessage(), resultCode);
  411. AvpSet ccrAvps = request.getMessage().getAvps();
  412. AvpSet ccaAvps = answer.getMessage().getAvps();
  413. // <Credit-Control-Answer> ::= < Diameter Header: 272, PXY >
  414. // < Session-Id >
  415. // { Result-Code }
  416. // { Origin-Host }
  417. // { Origin-Realm }
  418. // { Auth-Application-Id }
  419. // { CC-Request-Type }
  420. // Using the same as the one present in request
  421. ccaAvps.addAvp(ccrAvps.getAvp(416));
  422. // { CC-Request-Number }
  423. // Using the same as the one present in request
  424. ccaAvps.addAvp(ccrAvps.getAvp(415));
  425. // [ User-Name ]
  426. // [ CC-Session-Failover ]
  427. // [ CC-Sub-Session-Id ]
  428. // [ Acct-Multi-Session-Id ]
  429. // [ Origin-State-Id ]
  430. // [ Event-Timestamp ]
  431. // [ Granted-Service-Unit ]
  432. // 8.17. Granted-Service-Unit AVP
  433. //
  434. // Granted-Service-Unit AVP (AVP Code 431) is of type Grouped and
  435. // contains the amount of units that the Diameter credit-control client
  436. // can provide to the end user until the service must be released or the
  437. // new Credit-Control-Request must be sent. A client is not required to
  438. // implement all the unit types, and it must treat unknown or
  439. // unsupported unit types in the answer message as an incorrect CCA
  440. // answer. In this case, the client MUST terminate the credit-control
  441. // session and indicate in the Termination-Cause AVP reason
  442. // DIAMETER_BAD_ANSWER.
  443. //
  444. // The Granted-Service-Unit AVP is defined as follows (per the grouped-
  445. // avp-def of RFC 3588 [DIAMBASE]):
  446. //
  447. // Granted-Service-Unit ::= < AVP Header: 431 >
  448. // [ Tariff-Time-Change ]
  449. // [ CC-Time ]
  450. // [ CC-Money ]
  451. // [ CC-Total-Octets ]
  452. // [ CC-Input-Octets ]
  453. // [ CC-Output-Octets ]
  454. // [ CC-Service-Specific-Units ]
  455. // *[ AVP ]
  456. if(grantedUnits >= 0) {
  457. AvpSet gsuAvp = ccaAvps.addGroupedAvp(431);
  458. // Fetch AVP/Value from Request
  459. // gsuAvp.addAvp(ccrAvps.getAvp(437).getGrouped().getAvp(420));
  460. gsuAvp.addAvp(420, grantedUnits, true);
  461. }
  462. // *[ Multiple-Services-Credit-Control ]
  463. // [ Cost-Information]
  464. // [ Final-Unit-Indication ]
  465. // [ Check-Balance-Result ]
  466. // [ Credit-Control-Failure-Handling ]
  467. // [ Direct-Debiting-Failure-Handling ]
  468. // [ Validity-Time]
  469. // *[ Redirect-Host]
  470. // [ Redirect-Host-Usage ]
  471. // [ Redirect-Max-Cache-Time ]
  472. // *[ Proxy-Info ]
  473. // *[ Route-Record ]
  474. // *[ Failed-AVP ]
  475. // *[ AVP ]
  476. if(logger.isInfoEnabled()) {
  477. logger.info(">> Created Credit-Control-Answer.");
  478. DiameterUtilities.printMessage(answer.getMessage());
  479. }
  480. return answer;
  481. }
  482. private static String readFile(InputStream is) throws IOException {
  483. /*FileInputStream stream = new FileInputStream(is);
  484. try {
  485. FileChannel fc = stream.getChannel();
  486. MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
  487. // Instead of using default, pass in a decoder.
  488. return Charset.defaultCharset().decode(bb).toString();
  489. }
  490. finally {
  491. stream.close();
  492. }*/
  493. BufferedInputStream bin = new BufferedInputStream(is);
  494. byte[] contents = new byte[1024];
  495. int bytesRead = 0;
  496. String strFileContents;
  497. StringBuilder sb = new StringBuilder();
  498. while( (bytesRead = bin.read(contents)) != -1){
  499. strFileContents = new String(contents, 0, bytesRead);
  500. sb.append(strFileContents);
  501. }
  502. return sb.toString();
  503. }
  504. }