summaryrefslogtreecommitdiffstats
path: root/cpp/sca/samples/AlertAggregator/sample.alerter
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /cpp/sca/samples/AlertAggregator/sample.alerter
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/sca/samples/AlertAggregator/sample.alerter')
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/AlertCheckerImpl.py116
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/AlertConfigImpl.py175
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/Alerter.xsd73
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.py104
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.rb122
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/RSSCheckerImpl.py76
-rw-r--r--cpp/sca/samples/AlertAggregator/sample.alerter/sample.alerter.composite49
7 files changed, 715 insertions, 0 deletions
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/AlertCheckerImpl.py b/cpp/sca/samples/AlertAggregator/sample.alerter/AlertCheckerImpl.py
new file mode 100644
index 0000000000..d9aab820ac
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/AlertCheckerImpl.py
@@ -0,0 +1,116 @@
+# 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.
+#
+import xml.etree.ElementTree, datetime
+
+def getAllNewAlerts ():
+
+ returnXML = "<alerts xmlns=\"http://tuscany.apache.org/samples/alerter\">\n</alerts>"
+ returnElem = xml.etree.ElementTree.XML(returnXML)
+
+ # Use the alertConfigService to get the configuration
+ configElem = alertConfigService.getAlertConfig()
+
+ for sourceElem in configElem.findall("./{http://tuscany.apache.org/samples/alerter}source"):
+
+ sourceid = sourceElem.attrib["id"]
+
+ newAlerts = getAlerts(sourceElem)
+ if xml.etree.ElementTree.iselement(newAlerts):
+ # Add the sourceid to each alert and append to the entire list
+ for alert in newAlerts.findall("./{http://tuscany.apache.org/samples/alerter}alert"):
+ alert.attrib["sourceid"] = sourceid
+ returnElem.append(alert)
+
+ return returnElem
+
+def getAlerts (sourceElem):
+
+ lastcheckedElem = sourceElem.find("./{http://tuscany.apache.org/samples/alerter}lastChecked")
+ if not xml.etree.ElementTree.iselement(lastcheckedElem):
+ lastcheckedElem = xml.etree.ElementTree.SubElement(sourceElem, "lastChecked")
+ lastcheckedElem.text = ""
+
+ if sourceElem.attrib["type"] == "rss":
+
+ feedaddress = sourceElem.find("./{http://tuscany.apache.org/samples/alerter}feedAddress").text
+
+ if feedaddress:
+ # Use the rssCheckerService to get new articles for this config
+ newAlerts = rssCheckerService.getNewAlerts(feedaddress, lastcheckedElem.text)
+
+ lastcheckedElem.text = datetime.datetime.now().replace(microsecond=0).isoformat()
+ alertConfigService.updateSourceConfig(sourceElem)
+ return newAlerts
+
+ elif sourceElem.attrib["type"] == "pop":
+
+ popserver = sourceElem.find("./{http://tuscany.apache.org/samples/alerter}popServer").text
+ popusername = sourceElem.find("./{http://tuscany.apache.org/samples/alerter}popUsername").text
+ poppassword = sourceElem.find("./{http://tuscany.apache.org/samples/alerter}popPassword").text
+
+ if popserver and popusername and poppassword:
+ # Use the popCheckerService to get new emails for this config
+ newAlerts = popCheckerService.getNewAlerts(popserver, popusername, poppassword, lastcheckedElem.text)
+
+ lastcheckedElem.text = datetime.datetime.now().replace(microsecond=0).isoformat()
+ alertConfigService.updateSourceConfig(sourceElem)
+ return newAlerts
+
+ else:
+ print "Source type not supported: ", sourceElem.attrib["type"]
+
+ return None
+
+
+def getNewAlerts (sourceId):
+ # Use the alertConfigService to get the configuration
+ sourceConfigElem = alertConfigService.getSourceConfig(sourceId)
+
+ # Get the alerts
+ newAlerts = getAlerts(sourceConfigElem)
+
+ if xml.etree.ElementTree.iselement(newAlerts):
+ # Add the sourceid to each alert
+ for alert in newAlerts.findall("./{http://tuscany.apache.org/samples/alerter}alert"):
+ alert.attrib["sourceid"] = sourceId
+
+ return newAlerts
+
+def addAlertSource (sourceElem):
+ # Add the source directly to the configuration
+ return alertConfigService.addSourceConfig(sourceElem)
+
+def updateAlertSource (sourceElem):
+ # Update the source in the configuration
+ return alertConfigService.updateSourceConfig(sourceElem)
+
+def removeAlertSource (sourceId):
+ # Remove the source from the configuration
+ alertConfigService.removeSourceConfig(sourceId)
+
+def getAlertSources ():
+ # Get the config for all the sources
+ return alertConfigService.getAlertConfig()
+
+# # Testing
+# import AlertConfigImpl as alertConfigService
+# import RSSCheckerImpl as rssCheckerService
+# import POPCheckerImpl as popCheckerService
+#
+# print xml.etree.ElementTree.tostring(getAlertSources())
+# print xml.etree.ElementTree.tostring(getAllNewAlerts())
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/AlertConfigImpl.py b/cpp/sca/samples/AlertAggregator/sample.alerter/AlertConfigImpl.py
new file mode 100644
index 0000000000..2800a940b4
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/AlertConfigImpl.py
@@ -0,0 +1,175 @@
+# 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.
+#
+
+import xml.etree.ElementTree, os.path, os
+
+def getAlertConfig ():
+
+ # Set up some default config data
+ configData = "<config xmlns=\"http://tuscany.apache.org/samples/alerter\">\n</config>"
+
+ if os.path.isfile(os.environ['TUSCANY_SCACPP_ROOT']+"/config.xml"):
+ # Retrieve the configuration from a file
+ f = open(os.environ['TUSCANY_SCACPP_ROOT']+"/config.xml")
+ try:
+ configData = f.read()
+ finally:
+ f.close()
+
+ configElem = xml.etree.ElementTree.XML(configData)
+
+ return configElem
+
+def getSourceConfig (sourceId):
+
+ configElem = getAlertConfig()
+
+ for sourceElem in configElem.findall("./{http://tuscany.apache.org/samples/alerter}source"):
+ if sourceElem.attrib["id"] == sourceId:
+ return sourceElem
+
+ print "Source with id matching",sourceId,"not found"
+ return
+
+def updateSourceConfig (alertSourceConfigElem):
+
+ configElem = getAlertConfig()
+ sourceId = alertSourceConfigElem.attrib["id"]
+
+ for sourceElem in configElem.findall("./{http://tuscany.apache.org/samples/alerter}source"):
+ if sourceElem.attrib["id"] == sourceId:
+ configElem.remove(sourceElem)
+ configElem.append(alertSourceConfigElem)
+ saveConfigData(configElem)
+ return
+ print "Source with id matching",sourceId,"not found"
+ return
+
+def addSourceConfig (alertSourceConfigElem):
+ configElem = getAlertConfig()
+
+ #check for source ID, make sure it's not the same as others and create one if it's missing
+ if "id" in alertSourceConfigElem.attrib:
+ configId = alertSourceConfigElem.attrib["id"]
+ else:
+ configId = "0"
+
+ gotConfigId = False
+
+ while gotConfigId == False:
+
+ config = getSourceConfig(configId)
+ if config:
+ configId = str( int(configId)+1 )
+ else:
+ gotConfigId = True
+
+
+ alertSourceConfigElem.attrib["id"] = configId
+
+ configElem.append(alertSourceConfigElem)
+ saveConfigData(configElem)
+
+ return configId
+
+def saveConfigData (configElem):
+ configData = xml.etree.ElementTree.tostring(configElem)
+
+ # Save the configuration to a file
+ f = open(os.environ['TUSCANY_SCACPP_ROOT']+"/config.xml", "w")
+
+ if not f:
+ print "Failed to open config file for writing"
+ try:
+ f.write(configData)
+ finally:
+ f.close()
+
+def removeSourceConfig(sourceId):
+ configElem = getAlertConfig()
+ for sourceElem in configElem.findall("./{http://tuscany.apache.org/samples/alerter}source"):
+ if sourceElem.attrib["id"] == sourceId:
+ configElem.remove(sourceElem)
+ saveConfigData(configElem)
+ return
+
+# # Testing
+# if os.path.isfile("config.xml"):
+# os.remove("config.xml")
+# data = getAlertConfig()
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+# newsrcxml = "<source xmlns=\"http://tuscany.apache.org/samples/alerter\" type=\"rss\" id=\"0\">\n"
+# newsrcxml += "<name>PSP Updates</name>\n"
+# newsrcxml += "<address>http://pspupdates.qj.net</address>\n"
+# newsrcxml += "<feedAddress>http://pspupdates.qj.net/rss.xml</feedAddress></source>"
+#
+# newsrc = xml.etree.ElementTree.XML(newsrcxml)
+# ID = addSourceConfig(newsrc)
+# print "Added src with ID:", ID, "\n"
+#
+# newsrcxml = "<source xmlns=\"http://tuscany.apache.org/samples/alerter\" type=\"rss\" id=\"1\">\n"
+# newsrcxml += "<name>PSP Updates</name>\n"
+# newsrcxml += "<address>http://pspupdates.qj.net!</address>\n"
+# newsrcxml += "<feedAddress>http://pspupdates.qj.net/atom.xml</feedAddress></source>"
+#
+# newsrc = xml.etree.ElementTree.XML(newsrcxml)
+# ID = addSourceConfig(newsrc)
+# print "Added src with ID:", ID, "\n"
+#
+# data = getAlertConfig()
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+# data = getSourceConfig("0")
+# print xml.etree.ElementTree.tostring(data), "\n"
+# print dir(data), "\n"
+#
+# name = data.find("./{http://tuscany.apache.org/samples/alerter}name")
+# name.text = "Hello world!"
+#
+# updateSourceConfig(data)
+# data = getSourceConfig("1")
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+# removeSourceConfig("1")
+# data = getAlertConfig()
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+# ID = addSourceConfig(newsrc)
+# print "Added src with ID:", ID, "\n"
+#
+# ID = addSourceConfig(newsrc)
+# print "Added src with ID:", ID, "\n"
+#
+# data = getAlertConfig()
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+#
+# newsrcxml = "<source xmlns=\"http://tuscany.apache.org/samples/alerter\" type=\"rss\">\n"
+# newsrcxml += "<name>PSP Updates</name>\n"
+# newsrcxml += "<address>http://pspupdates.qj.net!</address>\n"
+# newsrcxml += "<feedAddress>http://pspupdates.qj.net/atom.xml</feedAddress></source>"
+#
+# newsrc = xml.etree.ElementTree.XML(newsrcxml)
+# ID = addSourceConfig(newsrc)
+# print "Added src with ID:", ID, "\n"
+#
+# data = getAlertConfig()
+# print xml.etree.ElementTree.tostring(data), "\n"
+#
+
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/Alerter.xsd b/cpp/sca/samples/AlertAggregator/sample.alerter/Alerter.xsd
new file mode 100644
index 0000000000..c59460995d
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/Alerter.xsd
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<schema targetNamespace="http://tuscany.apache.org/samples/alerter"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ns="http://tuscany.apache.org/samples/alerter">
+ <element name="alerts" type="ns:alerts"/>
+
+ <complexType name="alert">
+ <sequence>
+ <element name="title" type="string"/>
+ <element name="summary" type="string"/>
+ <element name="address" type="anyURI" maxOccurs="1" minOccurs="1"/>
+ <element name="date" type="string" maxOccurs="1" minOccurs="1"/>
+ </sequence>
+ <attribute name="sourceid" type="string" use="optional"/>
+ </complexType>
+
+ <complexType name="alerts">
+ <sequence>
+ <element name="alert" type="ns:alert" maxOccurs="unbounded" minOccurs="0" />
+ </sequence>
+ </complexType>
+
+ <element name="config" type="ns:config"/>
+ <element name="source" type="ns:source"/>
+
+ <complexType name="source">
+ <sequence>
+ <element name="name" type="string" maxOccurs="1" minOccurs="1"/>
+ <element name="address" type="anyURI" maxOccurs="1" minOccurs="1"/>
+ <element name="lastChecked" type="string" maxOccurs="1" minOccurs="0"/>
+ <element name="feedAddress" type="string" maxOccurs="1" minOccurs="0"/>
+ <element name="popServer" type="string" maxOccurs="1" minOccurs="0"/>
+ <element name="popUsername" type="string" maxOccurs="1" minOccurs="0"/>
+ <element name="popPassword" type="string" maxOccurs="1" minOccurs="0"/>
+ <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="id" type="string" use="optional"/>
+ <attribute name="type" use="required">
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="rss"/>
+ <enumeration value="pop"/>
+ <enumeration value="nntp"/>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+
+ <complexType name="config">
+ <sequence>
+ <element name="source" type="ns:source" maxOccurs="unbounded" minOccurs="0"/>
+ </sequence>
+ </complexType>
+</schema> \ No newline at end of file
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.py b/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.py
new file mode 100644
index 0000000000..0ae115ac2e
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.py
@@ -0,0 +1,104 @@
+# 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.
+#
+
+import poplib, email, datetime, re, xml.etree.ElementTree
+
+def getNewAlerts(popserver, username, password, lastchecktimestamp):
+
+ print "POPCheckerImpl getting new POP e-mail alerts\n"
+
+ alertsXML = "<alerts xmlns=\"http://tuscany.apache.org/samples/alerter\">\n"
+
+ # initially set lastchecked to the epoch before trying to use the lastchecked string
+ lastcheckdate = datetime.datetime.min
+ if lastchecktimestamp:
+ lastcheckdate = datetime.datetime.strptime(lastchecktimestamp, "%Y-%m-%dT%H:%M:%S")
+
+ numberOfNewEmails = 0
+
+ mail = poplib.POP3(popserver)
+ mail.user(username)
+ mail.pass_(password)
+ msgCount, inboxSize = mail.stat()
+
+ for msgNum in range(msgCount):
+
+ print "getting msg", msgNum+1, "of", msgCount
+
+ data = ""
+ for line in mail.retr(msgNum+1)[1]:
+ data += str(line)
+ data += "\n"
+
+ msg = email.message_from_string(data)
+
+ # date is of form "Sun, 21 Jan 2007 13:51:53 -0500"
+ msgDateString = msg.get("Date")
+ msgDateString, tz = msgDateString.rsplit(None, 1)
+
+ timezoneadjust = datetime.timedelta(0, (int(tz)/100)*60*60 + int(tz[3:5])*60)
+
+ msgdate = datetime.datetime.strptime(msgDateString, "%a, %d %b %Y %H:%M:%S") + timezoneadjust
+
+ if msgdate >= lastcheckdate:
+ msgTo = msg.get("To")
+ msgFrom = msg.get("From")
+ msgSubject = msg.get("Subject")
+
+ msgBody = ""
+ if msg.is_multipart():
+ for msgPart in msg.get_payload():
+ if msgPart.get_content_type() == "text/plain" or (msgPart.get_content_type() == "text/html" and msgBody == ""):
+ msgBody = msgPart.get_payload()
+ else:
+ msgBody = msg.get_payload()
+
+ alertsXML += "<alert><title>" + encodeXML(msgFrom) + " - "+encodeXML(msgSubject)+"</title>\n"
+ alertsXML += "<address></address>\n"
+ alertsXML += "<date>" + msgdate.isoformat() + "</date>\n"
+ alertsXML += "<summary>From: " + encodeXML(msgFrom)
+ alertsXML += "\nTo: "+encodeXML(msgTo)
+ alertsXML += "\nSubject: "+encodeXML(msgSubject)
+ alertsXML += "\nDate: " + msgdate.isoformat()
+ alertsXML += "\n\n" + stripXML(msgBody) + "</summary></alert>\n"
+
+
+ mail.quit()
+
+ alertsXML += "</alerts>"
+
+ return xml.etree.ElementTree.XML(alertsXML)
+
+
+def encodeXML(data):
+ data = re.sub("<","[", data)
+ data = re.sub(">","]", data)
+ return data
+
+def stripXML(data):
+ elementsRemoved = re.sub("<.*?>","", data)
+ entitiesRemoved = re.sub("&.*?;", " ", elementsRemoved)
+ asciiEncoded = entitiesRemoved.encode('ASCII', 'replace')
+ returnData = asciiEncoded.replace('&', 'and')
+ return returnData
+
+
+
+# Testing
+
+# print getNewAlerts("mail.eclipse.co.uk", "andrew@borley-hall.eclipse.co.uk", "app73sauc3", "2007-01-29T02:15:53")
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.rb b/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.rb
new file mode 100644
index 0000000000..e61046cb84
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/POPCheckerImpl.rb
@@ -0,0 +1,122 @@
+# 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.
+#
+
+require 'net/pop'
+require "rexml/document"
+include REXML
+
+# class POPChecker
+#
+# def initialize()
+# print "POPCheckerImpl.initialize\n"
+# end
+
+def getNewAlerts(popserver, username, password, lastchecked)
+
+ print "POPCheckerImpl getting new POP e-mail alerts\n"
+
+ alertsXML = "<alerts xmlns=\"http://tuscany.apache.org/samples/alerter\">\n"
+
+ # initially set lastchecked to the epoch before trying to use the lastchecked string
+ lastcheckedtime = Time.at(0)
+ if lastchecked != ''
+ # lastchecked (if provided) is of form 2007-02-17T23:34:56
+ year , month, day, hour, min, sec = lastchecked.split(/[-T:]/)
+ lastcheckedtime = Time.gm(year , month, day, hour, min, sec, nil)
+ end
+
+ numberOfEmails = 0
+
+ Net::POP3.start(popserver, 110, username, password) do |pop|
+
+ if !pop.mails.empty?
+ pop.each_mail do |m|
+ msg = m.pop
+
+ header, body = msg.split("\r\n\r\n", 2)
+ date = getMessageField("Date", header)
+ # date is of form "Sun, 21 Jan 2007 13:51:53 -0500"
+ parts = date.split(' ')
+ timeparts = parts[4].split(':')
+ timezoneSecs = (parts[5].to_i()/100)*60*60 + (parts[5].slice(-2,0).to_i())*60
+
+ msgtime = Time.gm(timeparts[2], timeparts[1], timeparts[0], parts[1], parts[2], parts[3], nil, nil, nil, nil) + timezoneSecs
+
+
+ if msgtime >= lastcheckedtime
+ from = getMessageField("From", header)
+ subject = getMessageField("Subject", header)
+
+ alertsXML += "<alert><title>From: " + encodeXML(from) + "\nSubject: "+encodeXML(subject)+"</title>\n"
+ alertsXML += "<address></address>\n"
+ alertsXML += "<date>" + msgtime.strftime("%Y-%m-%dT%H:%M:%S") + "</date>\n"
+ alertsXML += "<summary>" + stripXML(body) + "</summary></alert>\n"
+
+ numberOfEmails += 1
+ end
+
+ end
+ end
+ end
+ alertsXML += "</alerts>"
+
+ # Print XML
+ # puts alertsXML
+ print "POPCheckerImpl retrieved "+numberOfEmails.to_s+" new POP e-mail alerts\n"
+
+ # Return data as REXML document
+ result = Document.new(alertsXML)
+
+ return result
+end
+
+
+def getMessageField(field, message)
+
+ # Use a regex to get the field
+ pattern = '^'+field+': (.*?)$'
+
+ re = Regexp.new(pattern)
+ re =~ message
+
+ if $1 == nil
+ return ''
+ end
+
+ return $1
+end
+
+def encodeXML(data)
+ data = data.gsub(/</,'&lt;')
+ data = data.gsub(/>/,'&gt;')
+ return data
+end
+
+def stripXML(data)
+ data = data.gsub(/<.*?>/m,'')
+ data = data.gsub(/&.*?;/, ' ')
+ data = data.gsub(/&/, 'and')
+ data = encodeXML(data)
+ return data
+end
+
+
+
+# # Testing
+# pop = POPChecker.new()
+# print pop.getNewAlerts("mail.eclipse.co.uk", "andrew@borley-hall.eclipse.co.uk", "app73sauc3", "2007-01-29T02:15:53")
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/RSSCheckerImpl.py b/cpp/sca/samples/AlertAggregator/sample.alerter/RSSCheckerImpl.py
new file mode 100644
index 0000000000..2e320c0b22
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/RSSCheckerImpl.py
@@ -0,0 +1,76 @@
+# 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.
+#
+
+import feedparser, datetime, xml.etree.ElementTree, re
+
+def getNewAlerts(rssaddress, lastchecktimestamp):
+
+ print "RSSCheckerImpl.getNewAlerts() called", rssaddress, lastchecktimestamp
+
+ #Get and parse the RSS/Atom data
+ d = feedparser.parse(rssaddress)
+
+ newalertsxml = "<alerts xmlns=\"http://tuscany.apache.org/samples/alerter\">\n"
+
+ lastcheckdate = datetime.datetime.min
+ if lastchecktimestamp:
+ lastcheckdate = datetime.datetime.strptime(lastchecktimestamp, "%Y-%m-%dT%H:%M:%S")
+
+ defaultTitle = d.feed.get('title', 'RSS feed article')
+ defaultLink = d.feed.get('link', 'http://incubator.apache.org/tuscany')
+ defaultSummary = 'No information provided'
+
+ for entry in d.entries:
+
+ if entry.has_key('date'):
+ (year, month, day, hour, minute, second, millisecond, microsecond, tzinfo) = entry.date_parsed
+ entrydate = datetime.datetime(year, month, day, hour, minute, second)
+ else:
+ entrydate = datetime.datetime.now()
+
+
+ if (entrydate > lastcheckdate) :
+
+ newalertsxml += "<alert><title>" + stripXML(entry.get('title', defaultTitle)) + "</title>\n"
+ newalertsxml += "<address>" + entry.get('link', defaultLink) + "</address>\n"
+ newalertsxml += "<date>" + entrydate.isoformat() + "</date>\n"
+ newalertsxml += "<summary>" + stripXML(entry.get('description', defaultSummary)) + "</summary></alert>\n"
+ newalertsxml += "</alerts>"
+
+ return xml.etree.ElementTree.XML(newalertsxml)
+
+def stripXML(data):
+ elementsRemoved = re.sub("<.*?>","", data)
+ entitiesRemoved = re.sub("&.*?;", " ", elementsRemoved)
+ asciiEncoded = entitiesRemoved.encode('ASCII', 'replace')
+ returnData = asciiEncoded.replace('&', 'and')
+ return returnData
+
+
+# Testing
+# print xml.etree.ElementTree.tostring(getNewAlerts("http://www.engadget.com/rss.xml", "2007-02-07T17:11:14"))
+#
+#
+# today = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
+# data2 = getNewAlerts("http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml", today.isoformat())
+# print xml.etree.ElementTree.tostring(data2)
+#
+# print "1st call returned", len(data.findall("./{http://tuscany.apache.org/samples/alerter}alert")), "elements"
+# print "2nd call returned", len(data2.findall("./{http://tuscany.apache.org/samples/alerter}alert")), "elements"
+
+
diff --git a/cpp/sca/samples/AlertAggregator/sample.alerter/sample.alerter.composite b/cpp/sca/samples/AlertAggregator/sample.alerter/sample.alerter.composite
new file mode 100644
index 0000000000..21c4ee1093
--- /dev/null
+++ b/cpp/sca/samples/AlertAggregator/sample.alerter/sample.alerter.composite
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ name="sample.alerter">
+
+ <service name="AlerterService">
+ <binding.rest/>
+ <reference>AlertCheckerComponent</reference>
+ </service>
+
+ <component name="AlertCheckerComponent">
+ <implementation.python module="AlertCheckerImpl" scope="composite"/>
+ <reference name="alertConfigService">AlertConfigComponent</reference>
+ <reference name="rssCheckerService">RSSCheckerComponent</reference>
+ <reference name="popCheckerService">POPCheckerComponent</reference>
+ </component>
+
+ <component name="RSSCheckerComponent">
+ <implementation.python module="RSSCheckerImpl" scope="composite"/>
+ </component>
+
+ <component name="POPCheckerComponent">
+ <!--implementation.ruby script="POPCheckerImpl.rb" scope="stateless"/-->
+ <implementation.python module="POPCheckerImpl" scope="composite"/>
+ </component>
+
+ <component name="AlertConfigComponent">
+ <implementation.python module="AlertConfigImpl" scope="composite"/>
+ </component>
+
+</composite>