/*
* Copyright 2000-2001,2004 The Apache Software Foundation.
*
* 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.apache.jetspeed.webservices.finance.stockmarket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.HttpURLConnection;
import java.rmi.RemoteException;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.InputSource;
import org.apache.turbine.services.TurbineBaseService;
/**
Implements StockQuoteService,
providing a web service for getting stock quotes.
@author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
@version $Id: JetspeedStockQuoteService.java,v 1.7 2004/02/23 03:15:29 jford Exp $
*/
public class JetspeedStockQuoteService extends TurbineBaseService implements StockQuoteService
{
boolean debugIO = false;
PrintStream debugOutputStream = System.out;
// basic SOAP envelope
private static final String BASE_SOAP_ENVELOPE =
"<?xml version=\"1.0\"?>\n" +
"<SOAP-ENV:Envelope " +
"\n xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
"\n xmlns:xsd1=\"urn:DataQuoteService\"" +
"\n xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"" +
"\n xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
" <SOAP-ENV:Body>\n";
private static final String END_SOAP_ENVELOPE =
" </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\n";
private final static String SOAP_ENCODING = " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n";
// SOAP Service definitions
private static final String SERVICE_END_POINT =
"http://www.bluesunrise.com/webservices/container/BlueSunriseFinance/BlueSunriseFinanceService/BlueSunriseFinancePort/";
private static final String WSDL_SERVICE_NAMESPACE = "urn:QuoteService";
private static final String SOAP_METHOD_QUOTE = WSDL_SERVICE_NAMESPACE + "/quote";
private static final String SOAP_METHOD_FULLQUOTE = WSDL_SERVICE_NAMESPACE + "/fullQuote";
private static final String SOAP_METHOD_FULLQUOTES = WSDL_SERVICE_NAMESPACE + "/fullQuotes";
private String soapEndPoint = SERVICE_END_POINT;
// results
private static final String QUOTE_RESULT = "quoteResult";
private static final String FULL_QUOTE_RESULT = "fullQuoteResult";
private static final String FULL_QUOTES_RESULT = "fullQuotesResult";
private static final String DEFAULT_RETURN = "return";
/**
Get a single stock quote, given a symbol return the current price.
@param symbol The stock symbol.
@return String The current price.
*/
public String quote( String symbol )
throws RemoteException
{
StringBuffer envelope = new StringBuffer(BASE_SOAP_ENVELOPE);
envelope.append(" <m1:quote xmlns:m1=\"urn:QuoteService\"" );
envelope.append(SOAP_ENCODING);
envelope.append(" <symbol xsi:type=\"xsd:string\">");
envelope.append(symbol);
envelope.append("</symbol>\n");
envelope.append(" </m1:quote>\n");
envelope.append(END_SOAP_ENVELOPE);
SOAPResponseHandler handler = new SOAPResponseHandler(WSDL_SERVICE_NAMESPACE,
QUOTE_RESULT,
DEFAULT_RETURN);
doSOAPRequest(SOAP_METHOD_QUOTE, envelope, handler);
if (handler.isFault()) {
throw new RemoteException(handler.getFaultContent());
}
try
{
String resultString = handler.getResult();
if (resultString == null)
throw new RemoteException("Could not find return in soap response");
return resultString;
} catch (Exception e) {
throw new RemoteException("Error generating result.",e);
}
}
/**
Get a single stock quote record, given a symbol return a StockQuote object.
@param symbol The stock symbol.
@return StockQuote A full stock quote record.
*/
public StockQuote fullQuote( String symbol )
throws RemoteException
{
StringBuffer envelope = new StringBuffer(BASE_SOAP_ENVELOPE);
envelope.append(" <m1:fullQuote xmlns:m1=\"urn:QuoteService\"" );
envelope.append(SOAP_ENCODING);
envelope.append(" <symbol xsi:type=\"xsd:string\">");
envelope.append(symbol);
envelope.append("</symbol>\n");
envelope.append(" </m1:fullQuote>\n");
envelope.append(END_SOAP_ENVELOPE);
SOAPResponseHandler handler = new SOAPResponseHandler(WSDL_SERVICE_NAMESPACE,
FULL_QUOTE_RESULT,
DEFAULT_RETURN);
StockQuoteHandler quoteHandler = new StockQuoteHandler();
handler.setResultHandler(quoteHandler);
doSOAPRequest(SOAP_METHOD_FULLQUOTE, envelope, handler);
if (handler.isFault()) {
throw new RemoteException(handler.getFaultContent());
}
try {
return quoteHandler.getResult();
} catch (Exception e) {
throw new RemoteException("Error generating result.",e);
}
}
/**
Get an array of quote records, given a array of stock symbols.
@param symbols[] The array of stock symbols.
@return StockQuote[] An array of full stock quotes for each stock symbol.
*/
public StockQuote[] fullQuotes( String [] symbols )
throws RemoteException
{
if (null == symbols || symbols.length < 1)
throw new RemoteException("Invalid symbols[] parameter");
StringBuffer envelope = new StringBuffer(BASE_SOAP_ENVELOPE);
envelope.append(" <m1:fullQuotes xmlns:m1=\"urn:QuoteService\"" );
envelope.append(SOAP_ENCODING);
envelope.append(
" <symbols xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:string["+ symbols.length + "]\">\n");
for (int ix = 0; ix < symbols.length; ix++)
{
envelope.append(" <item xsi:type=\"xsd:string\">");
envelope.append(symbols[ix]);
envelope.append("</item>\n");
}
envelope.append(" ");
envelope.append("</symbols>\n");
envelope.append(" </m1:fullQuotes>\n");
envelope.append(END_SOAP_ENVELOPE);
SOAPResponseHandler handler = new SOAPResponseHandler(WSDL_SERVICE_NAMESPACE,
FULL_QUOTES_RESULT,
DEFAULT_RETURN);
StockQuoteArrayHandler quoteHandler = new StockQuoteArrayHandler();
handler.setResultHandler(quoteHandler);
doSOAPRequest(SOAP_METHOD_FULLQUOTES, envelope, handler);
if (handler.isFault()) {
throw new RemoteException(handler.getFaultContent());
}
try {
return quoteHandler.getResult();
} catch (Exception e) {
throw new RemoteException("Error generating result.",e);
}
}
/**
Set the name of the web service used by this service to retrieve stock quotes.
@param service The name of the web service.
*/
public void setWebService( String service )
{
this.soapEndPoint = service;
}
/**
Get the name of the web service used by this service to retrieve stock quotes.
@return String The name of the web service.
*/
public String getWebService()
{
return soapEndPoint;
}
/**
make a SOAP Request to the web service.
*/
private void doSOAPRequest(String soapAction, StringBuffer envelope, XMLFilterImpl handler)
throws RemoteException
{
try {
if (debugIO) {
debugOutputStream.println("SOAPURL: "+soapEndPoint);
debugOutputStream.println("SoapAction: "+soapAction);
debugOutputStream.println("SoapEnvelope:");
debugOutputStream.println(envelope.toString());
}
URL url = new URL(soapEndPoint);
HttpURLConnection connect = (HttpURLConnection)url.openConnection();
connect.setDoOutput(true);
byte bytes[] = envelope.toString().getBytes();
connect.setRequestProperty("SOAPAction","\""+soapAction+"\"");
connect.setRequestProperty("content-type","text/xml");
connect.setRequestProperty("content-length",""+bytes.length);
OutputStream out = connect.getOutputStream();
out.write(bytes);
out.flush();
int rc = connect.getResponseCode();
InputStream stream = null;
if (rc == HttpURLConnection.HTTP_OK) {
stream = connect.getInputStream();
} else if (rc == HttpURLConnection.HTTP_INTERNAL_ERROR) {
stream = connect.getErrorStream();
}
if (stream != null) {
if (debugIO) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int bt = stream.read();
while (bt != -1) {
bout.write(bt);
bt = stream.read();
}
debugOutputStream.println("Response:");
debugOutputStream.println(new String(bout.toByteArray()));
stream.close();
stream = new ByteArrayInputStream(bout.toByteArray());
}
String contentType = connect.getContentType();
if (contentType.indexOf("text/xml") == -1) {
throw new RemoteException("Content-type not text/xml. Instead, found "+contentType);
}
org.apache.xerces.parsers.SAXParser xmlreader = new org.apache.xerces.parsers.SAXParser();
// TODO TODO
// uncomment this block and comment out the above line to use a generic parser
//SAXParserFactory factory = SAXParserFactory.newInstance();
//factory.setNamespaceAware(true);
//SAXParser saxparser = factory.newSAXParser();
//XMLReader xmlreader = saxparser.getXMLReader();
handler.setParent(xmlreader);
xmlreader.setContentHandler(handler);
xmlreader.parse(new InputSource(stream));
stream.close();
} else {
throw new RemoteException("Communication error: "+rc+" "+connect.getResponseMessage());
}
} catch (RemoteException rex) {
throw rex;
} catch (Exception ex) {
throw new RemoteException("Error doing soap stuff",ex);
}
}
///////////////////////////////////////////////////////////////////////////
/**
usage:
java JetspeedStockQuoteService [option] method [params]
method: parameter: description:
----------------------------------------------------------------------
quote symbol get the price for the given symbol
quotes symbols.. get the prices for 1..n symbols
fullQuote symbol get a stock quote record for the given symbol
fullQuotes symbols... 1..n symbols to look up multiple stock quote records
options:
--------
-debug print to stdout the SOAP request and response packets
Examples:
java JetspeedStockQuoteService quote IBM
java JetspeedStockQuoteService quotes IONA CSCO NOK ADSK
java JetspeedStockQuoteService -debug fullQuote DST
java JetspeedStockQuoteService fullQuotes SUNW MSFT ORCL
**/
public static void main (String args[]) {
try {
JetspeedStockQuoteService service = new JetspeedStockQuoteService();
if (args.length == 0) {
return;
}
int index = 0;
// any options
if (args[index].startsWith("-"))
{
if ("-debug".equals(args[0]))
{
service.debugIO = true;
index++;
}
}
if (index >= args.length)
return;
if ("quote".equals(args[index]))
{
index++;
if (index >= args.length)
return;
System.out.println( service.quote(args[index]) );
}
else if ("quotes".equals(args[index]))
{
// NOT YET IMPLEMENTED
}
else if ("fullQuote".equals(args[index]))
{
index++;
if (index >= args.length)
return;
System.out.println( service.fullQuote(args[index]));
}
else if ("fullQuotes".equals(args[index]))
{
index++;
String[] symbols = new String[args.length - index];
for (int ix = 0 ; ix < symbols.length; ix++)
{
symbols[ix] = args[index];
index++;
}
StockQuote[] stocks = service.fullQuotes( symbols );
for (int ix = 0; ix < stocks.length; ix++)
System.out.println( stocks[ix] );
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}