client1 can send txt message to client2 using
connection.getChatManager().createChat(to, this).sendMessage(message);
How to send other kind of message: like INFO message ? (client1 to client2) ?
Because I want, INFO message should not be displayed in the chat window....is it possible ? using smack, smackx library.
Many Thanks.
What you want do do here is to add an extension to your text message. Here is a rough guide.
Chat chat = connection.getChatManager().createChat(to, this);
Message message = new Message(to, Message.Type.chat);
message.setBody("hello");
message.setProperty(prop0, val0);
message.setProperty(prop1, val1);
chat.sendMessage(message)
The properties are carried in a separate namespace (use toXML() to look at it) and will not appear in the chat window. On the 'other side', the applications uses getProperty() to retrieve the value.
If you do not want key/value pairs, but structured data, use addExtension() in the message body. This is a little more complicated because you basically have to extend PacketExtension, provide your own namespace. You might even have to write a PacketExtensionProvider.
Here is the example for message extension.
The basic XML structure of the XMPP protocol is:
<message
from='sender_jid'
to='receiver_jid'
type='message_type'>
<body> content </body>
</message>
The process of sending messages:
//build chat
Chat chat = chatManager.createChat("jid");
//build extension
UserInfo4XMPP userInfo4XMPP = new UserInfo4XMPP();
userInfo4XMPP.setNameText("userx");
userInfo4XMPP.setUrlText("http://www.liaoku.org/");
//build message
Message message = new Message();
message.setBody("hello");
message.addExtension(userInfo4XMPP);// add the extension
//send
chat.sendMessage(message);
The UserInfo4XMPP is defined as:
import org.jivesoftware.smack.packet.ExtensionElement;
public class UserInfo4XMPP implements ExtensionElement{
private String elementName = "userinfo";
private String nameElement = "name";
private String urlElement = "url";
private String nameText = "";
private String urlText = "";
#Override
public String getElementName() {
return elementName;
}
#Override
public CharSequence toXML() {
StringBuilder sb = new StringBuilder();
sb.append("<");
sb.append(elementName);
sb.append(">");
sb.append("<");
sb.append(nameElement);
sb.append(">");
sb.append(nameText);
sb.append("</");
sb.append(nameElement);
sb.append(">");
sb.append("<");
sb.append(urlElement);
sb.append(">");
sb.append(urlText);
sb.append("</");
sb.append(urlElement);
sb.append(">");
sb.append("</");
sb.append(elementName);
sb.append(">");
return sb.toString();
}
#Override
public String getNamespace() {
return "";
}
public String getNameText() {
return nameText;
}
public void setNameText(String nameText) {
this.nameText = nameText;
}
public String getUrlText() {
return urlText;
}
public void setUrlText(String urlText) {
this.urlText = urlText;
}
}
A more complicated example of message extention:
Message videoMsg = new Message();
VideoChatRTP videoXml = new VideoChatRTP();
videoXml.setVideoType(VideoMediaType.REQUEST);
videoXml.setAddress(address);
videoMsg.setTo(receive);
videoMsg.addExtension(videoXml);
XMPPConnection conn = BaseService.getInstance().getConnection();
conn.sendPacket(videoMsg);
The extension class VideoChatRIP must implement PacketExtension:
public class VideoChatRTP implements PacketExtension {
private VideoMediaType videoType;
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public VideoMediaType getVideoType() {
return videoType;
}
public void setVideoType(VideoMediaType videoType) {
this.videoType = videoType;
}
public static final String NAME = "jingle";
public static final String NAME_SPACE = "com:roger:video";
public VideoChatRTP() {
super();
}
#Override
public String getElementName() {
return NAME;
}
#Override
public String getNamespace() {
return NAME_SPACE;
}
#Override
public String toXML() {
StringBuffer sb = new StringBuffer();
sb.append("<jingle").append(" xmlns=\"").append(NAME_SPACE).append(
"\">");
sb.append("<type>").append(videoType).append("</type>");
sb.append("<ipAddress>").append(address).append("</ipAddress>");
sb.append("</jingle>");
return sb.toString();
}
}
The Listener:
ProviderManager.getInstance().addExtensionProvider(VideoChatRTP.NAME, VideoChatRTP.NAME_SPACE, new VideoChatReceive());
Processing:
public class VideoChatReceive implements PacketExtensionProvider {
#Override
public PacketExtension parseExtension(XmlPullParser parser)
throws Exception {
boolean done = false;
String requestType = "asdasd";
String ipAddress = "asdasd";
while (!done) {
int eventType = parser.next();
String name = parser.getName();
if (eventType == XmlPullParser.START_TAG) {
if (name.equals("type")) {
requestType = parser.nextText();
}
if (name.equals("ipAddress")) {
ipAddress = parser.nextText();
}
}
if (eventType == XmlPullParser.END_TAG) {
if (name.equals("jingle")) {
done = true;
}
}
}
VideoChatRTP videoRtp = new VideoChatRTP();
videoRtp.setVideoType(VideoMediaType.valueOf(requestType));
videoRtp.setAddress(ipAddress);
return videoRtp;
}
}
Related
this is my first question here. do not judge strictly:) I'm parsing a file with the dim extension of the xml format, in fact, so I chose SAXparser. the problem is probably architectural or I don’t know how to call it correctly. in general, if you describe: there is a list of tags that I need to pull out and, in accordance with them, create objects, assign values to their fields, which the parser will pull out as strings from certain tags. in accordance with the tags I need, I have implemented classes with which I need to create objects in the startElement method, after that in endElement I need to assign the appropriate strings to this object. The crux of the problem is that I can't figure out how I can avoid a lot of code in the SaxParserHandler class, including a lot of if/else in the startElement and endElement methods. tried to use enum and factory pattern, but all in vain. example of my current code in SaxParserHandler:
public class SaxParserHandler extends DefaultHandler {
private Dataset_Id dataset_id = null;
private StringBuilder data = null;
private Dataset_Frame dataset_frame = null;
private String MetadataId = "Metadata_Id";
private String dataset_name_tag = "DATASET_NAME";
private String dataset_frame_tag = "Dataset_Frame";
private Vertex vertex = null;
private List<Vertex> vertices = null;
private String vertex_tag = "Vertex";
private String FRAME_LON = "FRAME_LON";
private String FRAME_LAT = "FRAME_LAT";
private String FRAME_X = "FRAME_X";
private String FRAME_Y = "FRAME_Y";
private String FRAME_ROW = "FRAME_ROW";
private String FRAME_COL = "FRAME_COL";
private Source_Information source_information = null;
private Scene_Source scene_source = null;
private String source_info_tag = "Source_Information";
private String source_id_tag = "SOURCE_ID";
private String scene_source_tag = "Scene_Source";
private String imaging_date_tag = "IMAGING_DATE";
private String imaging_time_tag = "IMAGING_TIME";
private String mission_tag = "MISSION";
private String mission_index_tag = "MISSION_INDEX";
private String instrument_tag = "INSTRUMENT";
private String satellite_incidence_angle_tag = "SATELLITE_INCIDENCE_ANGLE";
private String viewing_angle_tag = "VIEWING_ANGLE";
private String sun_azimuth_tag = "SUN_AZIMUTH";
private String sun_elevation_tag = "SUN_ELEVATION";
private String theoretical_resolution_tag = "THEORETICAL_RESOLUTION";
private Coordinate_Reference_System coordinate_reference_system = null;
private Horizontal_CS horizontal_cs = null;
private String Coordinate_Reference_System_Tag = "Coordinate_Reference_System";
private String Horizontal_CS_Tag = "Horizontal_CS";
private String HORIZONTAL_CS_CODE_TAG = "HORIZONTAL_CS_CODE";
private String HORIZONTAL_CS_TYPE_TAG = "HORIZONTAL_CS_TYPE";
private String HORIZONTAL_CS_NAME_TAG = "HORIZONTAL_CS_NAME";
private Production production = null;
private Production_Facility production_facility = null;
private String Production_Tag = "Production";
private String DATASET_PRODUCTION_DATE_TAG = "DATASET_PRODUCTION_DATE";
private String PRODUCT_TYPE_TAG = "PRODUCT_TYPE";
private String PRODUCT_INFO_TAG = "PRODUCT_INFO";
private String JOB_ID_TAG = "JOB_ID";
private String Production_Facility_Tag = "Production_Facility";
private String SOFTWARE_NAME_TAG = "SOFTWARE_NAME";
private String SOFTWARE_VERSION_TAG = "SOFTWARE_VERSION";
private String PROCESSING_CENTER_TAG = "PROCESSING_CENTER";
private Raster_Encoding raster_encoding = null;
private String Raster_Encoding_Tag = "Raster_Encoding";
private String DATA_TYPE_TAG = "DATA_TYPE";
private String NBITS_TAG = "NBITS";
private String BYTEORDER_TAG = "BYTEORDER";
private String BANDS_LAYOUT_TAG = "BANDS_LAYOUT";
private Data_Processing data_processing = null;
private String Data_Processing_Tag = "Data_Processing";
private String PROCESSING_LEVEL_TAG = "PROCESSING_LEVEL";
private String GEOMETRIC_PROCESSING_TAG = "GEOMETRIC_PROCESSING";
private String RADIOMETRIC_PROCESSING_TAG = "RADIOMETRIC_PROCESSING";
private Data_Access data_access = null;
private Data_File_List data_file_list = null;
private String Data_Access_Tag = "Data_Access";
private String DATA_FILE_FORMAT_TAG = "DATA_FILE_FORMAT";
private String DATA_FILE_ORGANISATION_TAG = "DATA_FILE_ORGANISATION";
private String Data_File_List_Tag = "Data_File_List";
private String DATA_FILE_PATH_TAG = "DATA_FILE_PATH";
private Image_Display image_display = null;
private Band_Display_Order band_display_order = null;
private String Image_Display_Tag = "Image_Display";
private String Band_Display_Order_Tag = "Band_Display_Order";
private String RED_CHANNEL_TAG = "RED_CHANNEL";
private String GREEN_CHANNEL_TAG = "GREEN_CHANNEL";
private String BLUE_CHANNEL_TAG = "BLUE_CHANNEL";
private Data_Strip data_strip = null;
private Data_Strip_Identification data_strip_identification = null;
private Time_Stamp time_stamp = null;
private Ephemeris ephemeris = null;
private String Data_Strip_Tag = "Data_Strip";
private String Data_Strip_Identification_Tag = "Data_Strip_Identification";
private String DATA_STRIP_ID_TAG = "DATA_STRIP_ID";
private String SEGMENT_ID_TAG = "SEGMENT_ID";
private String Time_Stamp_Tag = "Time_Stamp";
private String REFERENCE_BAND_TAG = "REFERENCE_BAND";
private String REFERENCE_TIME_TAG = "REFERENCE_TIME";
private String REFERENCE_LINE_TAG = "REFERENCE_LINE";
private String LINE_PERIOD_TAG = "LINE_PERIOD";
private String Ephemeris_Tag = "Ephemeris";
private String SATELLITE_ALTITUDE_TAG = "SATELLITE_ALTITUDE";
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase(dataset_name_tag))
dataset_id = new Dataset_Id();
else if (qName.equalsIgnoreCase(dataset_frame_tag)) {
dataset_frame = new Dataset_Frame();
} else if (qName.equals(vertex_tag)) {
vertex = new Vertex();
if (vertices == null)
vertices = new ArrayList<>();
} else if (qName.equalsIgnoreCase(source_info_tag)) {
source_information = new Source_Information();
} else if (qName.equals(scene_source_tag)) {
scene_source = new Scene_Source();
} else if (qName.equals(Coordinate_Reference_System_Tag)) {
coordinate_reference_system = new Coordinate_Reference_System();
} else if (qName.equals(Horizontal_CS_Tag)) {
horizontal_cs = new Horizontal_CS();
} else if (qName.equals(Production_Tag)) {
production = new Production();
} else if (qName.equals(Production_Facility_Tag)) {
production_facility = new Production_Facility();
} else if (qName.equals(Raster_Encoding_Tag)) {
raster_encoding = new Raster_Encoding();
} else if (qName.equals(Data_Processing_Tag)) {
data_processing = new Data_Processing();
} else if (qName.equals(Data_Access_Tag)) {
data_access = new Data_Access();
} else if (qName.equals(Data_File_List_Tag)) {
data_file_list = new Data_File_List();
}else if (qName.equals(Image_Display_Tag)) {
image_display = new Image_Display();
}else if (qName.equals(Band_Display_Order_Tag)) {
band_display_order = new Band_Display_Order();
}else if (qName.equals(Data_Strip_Tag)){
data_strip = new Data_Strip();
}else if (qName.equals(Data_Strip_Identification_Tag)) {
data_strip_identification = new Data_Strip_Identification();
}else if (qName.equals(Time_Stamp_Tag)) {
time_stamp = new Time_Stamp();
}else if (qName.equals(Ephemeris_Tag)) {
ephemeris = new Ephemeris();
}
data = new StringBuilder();
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals(dataset_name_tag)) {
dataset_id.setDataset_name(data.toString());
} else if (qName.equals(FRAME_LON)) {
vertex.setFRAME_LON(data.toString());
} else if (qName.equals(FRAME_LAT)) {
vertex.setFRAME_LAT(data.toString());
} else if (qName.equals(FRAME_X)) {
vertex.setFRAME_X(data.toString());
} else if (qName.equals(FRAME_Y)) {
vertex.setFRAME_Y(data.toString());
} else if (qName.equals(FRAME_ROW)) {
vertex.setFRAME_ROW(data.toString());
} else if (qName.equals(FRAME_COL)) {
vertex.setFRAME_COL(data.toString());
} else if (qName.equals(vertex_tag)) {
vertices.add(vertex);
} else if (qName.equals(dataset_frame_tag)) {
dataset_frame.setDataset_Frame(vertices);
} else if (qName.equals(source_id_tag)) {
source_information.setSource_id(data.toString());
} else if (qName.equals(imaging_date_tag)) {
scene_source.setIMAGING_DATE(data.toString());
} else if (qName.equals(imaging_time_tag)) {
scene_source.setIMAGING_TIME(data.toString());
} else if (qName.equals(mission_tag)) {
scene_source.setMISSION(data.toString());
} else if (qName.equals(mission_index_tag)) {
scene_source.setMISSION_INDEX(data.toString());
} else if (qName.equals(instrument_tag)) {
scene_source.setINSTRUMENT(data.toString());
} else if (qName.equals(satellite_incidence_angle_tag)) {
scene_source.setSATELLITE_INCIDENCE_ANGLE(data.toString());
} else if (qName.equals(viewing_angle_tag)) {
scene_source.setVIEWING_ANGLE(data.toString());
} else if (qName.equals(sun_azimuth_tag)) {
scene_source.setSUN_AZIMUTH(data.toString());
} else if (qName.equals(sun_elevation_tag)) {
scene_source.setSUN_ELEVATION(data.toString());
} else if (qName.equals(theoretical_resolution_tag)) {
scene_source.setTHEORETICAL_RESOLUTION(data.toString());
} else if (qName.equals(source_info_tag)) {
source_information.setScene_source(scene_source);
} else if (qName.equals(HORIZONTAL_CS_TYPE_TAG)) {
horizontal_cs.setHORIZONTAL_CS_TYPE(data.toString());
} else if (qName.equals(HORIZONTAL_CS_NAME_TAG)) {
horizontal_cs.setHORIZONTAL_CS_NAME(data.toString());
} else if (qName.equals(HORIZONTAL_CS_CODE_TAG)) {
horizontal_cs.setHORIZONTAL_CS_CODE(data.toString());
} else if (qName.equals(Horizontal_CS_Tag)) {
coordinate_reference_system.setHorizontal_cs(horizontal_cs);
} else if (qName.equals(DATASET_PRODUCTION_DATE_TAG)) {
production.setDATASET_PRODUCTION_DATE(data.toString());
} else if (qName.equals(PRODUCT_TYPE_TAG)) {
production.setPRODUCT_TYPE(data.toString());
} else if (qName.equals(PRODUCT_INFO_TAG)) {
production.setPRODUCT_INFO(data.toString());
} else if (qName.equals(JOB_ID_TAG)) {
production.setJOB_ID(data.toString());
} else if (qName.equals(SOFTWARE_NAME_TAG)) {
production_facility.setSOFTWARE_NAME(data.toString());
} else if (qName.equals(SOFTWARE_VERSION_TAG)) {
production_facility.setSOFTWARE_VERSION(data.toString());
} else if (qName.equals(PROCESSING_CENTER_TAG)) {
production_facility.setPROCESSING_CENTER(data.toString());
} else if (qName.equals(Production_Tag)) {
production.setProduction_facility(production_facility);
} else if (qName.equals(DATA_TYPE_TAG)) {
raster_encoding.setDATA_TYPE(data.toString());
} else if (qName.equals(NBITS_TAG)) {
raster_encoding.setNBITS(data.toString());
} else if (qName.equals(BYTEORDER_TAG)) {
raster_encoding.setBYTEORDER(data.toString());
} else if (qName.equals(BANDS_LAYOUT_TAG)) {
raster_encoding.setBANDS_LAYOUT(data.toString());
} else if (qName.equals(PROCESSING_LEVEL_TAG)) {
data_processing.setPROCESSING_LEVEL(data.toString());
} else if (qName.equals(GEOMETRIC_PROCESSING_TAG)) {
data_processing.setGEOMETRIC_PROCESSING(data.toString());
} else if (qName.equals(RADIOMETRIC_PROCESSING_TAG)) {
data_processing.setRADIOMETRIC_PROCESSING(data.toString());
} else if (qName.equals(DATA_FILE_FORMAT_TAG)) {
data_access.setDATA_FILE_FORMAT(data.toString());
} else if (qName.equals(DATA_FILE_ORGANISATION_TAG)) {
data_access.setDATA_FILE_ORGANISATION(data.toString());
} else if (qName.equals(DATA_FILE_PATH_TAG)) {
data_file_list.setDATA_FILE_PATH(data.toString());
} else if (qName.equals(Data_File_List_Tag)) {
data_access.setData_file_lists(data_file_list);
}else if (qName.equals(RED_CHANNEL_TAG)) {
band_display_order.setRED_CHANNEL(data.toString());
}else if (qName.equals(GREEN_CHANNEL_TAG)) {
band_display_order.setGREEN_CHANNEL(data.toString());
}else if (qName.equals(BLUE_CHANNEL_TAG)) {
band_display_order.setBLUE_CHANNEL(data.toString());
}else if (qName.equals(Band_Display_Order_Tag)) {
image_display.setBand_display_orders(band_display_order);
}else if (qName.equals(DATA_STRIP_ID_TAG)){
data_strip_identification.setDATA_STRIP_ID(data.toString());
}else if (qName.equals(SEGMENT_ID_TAG)) {
data_strip_identification.setSEGMENT_ID(data.toString());
}else if (qName.equals(Data_Strip_Identification_Tag)) {
data_strip.setData_strip_identification(data_strip_identification);
}else if (qName.equals(REFERENCE_BAND_TAG)) {
time_stamp.setREFERENCE_BAND(data.toString());
}else if (qName.equals(REFERENCE_TIME_TAG)){
time_stamp.setREFERENCE_TIME(data.toString());
}else if (qName.equals(REFERENCE_LINE_TAG)) {
time_stamp.setREFERENCE_LINE(data.toString());
}else if (qName.equals(LINE_PERIOD_TAG)) {
time_stamp.setLINE_PERIOD(data.toString());
}else if (qName.equals(Time_Stamp_Tag)) {
data_strip.setTime_stamp(time_stamp);
}else if (qName.equals(SATELLITE_ALTITUDE_TAG)) {
ephemeris.setSATELLITE_ALTITUDE(data.toString());
}else if (qName.equals(Ephemeris_Tag)) {
data_strip.setEphemerises(ephemeris);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
data.append(new String(ch, start, length));
}
Root root = new Root();
public Root getRoot() {
root.setDataset_id(dataset_id);
root.setDataset_frame(dataset_frame);
root.setSource_information(source_information);
root.setCoordinate_reference_systems(coordinate_reference_system);
root.setProductions(production);
root.setRaster_encodings(raster_encoding);
root.setData_processings(data_processing);
root.setData_accesses(data_access);
root.setImage_displays(image_display);
root.setData_strips(data_strip);
return root;
}
}
part of dim file sample
<?xml version="1.0" encoding="ISO-8859-1"?>
<Dimap_Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Metadata_Id>
<METADATA_FORMAT version="1.1">DIMAP</METADATA_FORMAT>
</Metadata_Id>
<Dataset_Id>
<DATASET_NAME>KM000604MI_017_MUL_L1G</DATASET_NAME>
<DATASET_TN_PATH href="KM000604MI_017_MUL_L1G_tn.jpg"/>
<DATASET_QL_PATH href="KM000604MI_017_MUL_L1G_ql.jpg"/>
</Dataset_Id>
<Production>
<DATASET_PRODUCER_NAME/>
<DATASET_PRODUCTION_DATE>2015-09-28</DATASET_PRODUCTION_DATE>
<PRODUCT_TYPE/>
</Production>
<Dataset_Use>
<DATASET_CONTENT/>
</Dataset_Use>
<Data_Processing>
<GEOMETRIC_PROCESSING/>
<Processing_Parameter>
<PROC_PARAMETER_DESC>SOFTWARE</PROC_PARAMETER_DESC>
<PROC_PARAMETER_VALUE>Keystone 3.8.9.FINAL.</PROC_PARAMETER_VALUE>
</Processing_Parameter>
</Data_Processing>
<Coordinate_Reference_System>
<GEO_TABLES>EPSG</GEO_TABLES>
<Horizontal_CS>
<HORIZONTAL_CS_CODE>EPSG:32642</HORIZONTAL_CS_CODE>
<HORIZONTAL_CS_TYPE>PROJECTED</HORIZONTAL_CS_TYPE>
<HORIZONTAL_CS_NAME>WGS 84 / UTM zone 42N</HORIZONTAL_CS_NAME>
<Coordinate_Axis>
<AXIS1_NAME>Easting</AXIS1_NAME>
<AXIS2_NAME>Northing</AXIS2_NAME>
<AXIS1_ORIENTATION>EAST</AXIS1_ORIENTATION>
<AXIS2_ORIENTATION>NORTH</AXIS2_ORIENTATION>
</Coordinate_Axis>
<Projection>
<PROJECTION_NAME>UTM zone 42N</PROJECTION_NAME>
<PROJECTION_CODE>EPSG:16042</PROJECTION_CODE>
<Projection_CT_Method>
<PROJECTION_CT_NAME>Transverse Mercator</PROJECTION_CT_NAME>
<PROJECTION_CT_CODE>EPSG:9807</PROJECTION_CT_CODE>
<Projection_Parameters>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Latitude_of_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="DEG">0.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Longitude_of_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="DEG">69.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>Scale_factor_at_natural_origin</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE>0.9996</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>False_easting</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="M">500000.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
<Projection_Parameter>
<PROJECTION_PARAMETER_NAME>False_northing</PROJECTION_PARAMETER_NAME>
<PROJECTION_PARAMETER_VALUE unit="M">0.0</PROJECTION_PARAMETER_VALUE>
</Projection_Parameter>
</Projection_Parameters>
</Projection_CT_Method>
</Projection>
<Geographic_CS>
<GEOGRAPHIC_CS_NAME>WGS 84</GEOGRAPHIC_CS_NAME>
<GEOGRAPHIC_CS_CODE>EPSG:4326</GEOGRAPHIC_CS_CODE>
<Horizontal_Datum>
<HORIZONTAL_DATUM_NAME>World Geodetic System 1984</HORIZONTAL_DATUM_NAME>
<HORIZONTAL_DATUM_CODE>EPSG:6326</HORIZONTAL_DATUM_CODE>
<Ellipsoid>
<ELLIPSOID_NAME>WGS 84</ELLIPSOID_NAME>
<ELLIPSOID_CODE>EPSG:7030</ELLIPSOID_CODE>
<Ellipsoid_Parameters>
<ELLIPSOID_MAJOR_AXIS unit="M">6378137.0</ELLIPSOID_MAJOR_AXIS>
<ELLIPSOID_MINOR_AXIS unit="M">6356752.314245</ELLIPSOID_MINOR_AXIS>
</Ellipsoid_Parameters>
</Ellipsoid>
<Prime_Meridian>
<PRIME_MERIDIAN_NAME>Greenwich</PRIME_MERIDIAN_NAME>
<PRIME_MERIDIAN_CODE>EPSG:8901</PRIME_MERIDIAN_CODE>
<PRIME_MERIDIAN_OFFSET unit="DEG">0.0</PRIME_MERIDIAN_OFFSET>
</Prime_Meridian>
</Horizontal_Datum>
</Geographic_CS>
</Horizontal_CS>
</Coordinate_Reference_System>
If you are open to use third party libraries, you might give Jsoup a try. Jsoup is actually a HTML-parser but is also able to parse XML. It provides IMHO an intuitive and simple selector syntax and API which you can use to get the elements you are interested in.
I am not realy sure what you are trying to achieve and didn't find all the tags from your code in the sample xml you provided. But to give you a simple starting point on how to use Jsoup, please see below snippet where I fetch the
Production DATASET_PRODUCTION_DATE and the Projection_Parameters from the sample xml:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
public class Example2 {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("path to your xml file"));
Document doc = Jsoup.parse(in, "UTF-8", "", Parser.xmlParser());
String productionDate = doc.selectFirst("Production DATASET_PRODUCTION_DATE").text();
System.out.println("PRODUCTION_DATE: " + productionDate);
Elements projection_Parameters = doc.select("Projection_Parameter");
projection_Parameters.forEach(param -> {
String name = param.selectFirst("PROJECTION_PARAMETER_NAME").text();
String value = param.selectFirst("PROJECTION_PARAMETER_VALUE").text();
System.out.printf("NAME: %s, VALUE: %s %n", name, value);
});
}
}
output:
PRODUCTION_DATE: 2015-09-28
NAME: Latitude_of_natural_origin, VALUE: 0.0
NAME: Longitude_of_natural_origin, VALUE: 69.0
NAME: Scale_factor_at_natural_origin, VALUE: 0.9996
NAME: False_easting, VALUE: 500000.0
NAME: False_northing, VALUE: 0.0
Instead of printing to console you could of course create directly your POJOs. If interested get Jsoup from Maven central
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Iam trying to make login activity
I got a problem. My setter doesnt work, i dont know why?
I have 3 classes.
1st one is Data with server data and getters and setters
public class Data{
String addressesURL = "/DataSnap/rest/TServerMethods1/LookupCustomers";
String articlesURL = "/DataSnap/rest/TServerMethods1/LookupArticle";
String invoicesURL = "/DataSnap/rest/TServerMethods1/LookupInvoice";
String invoicesDetailsURL = "/DataSnap/rest/TServerMethods1/LookupInvoicePos";
String invoicesDetailsAddressesURL = "/DataSnap/rest/TServerMethods1/LookupInvoiceAddress";
String ordersURL = "/DataSnap/rest/TServerMethods1/LookupOrders";
String ordersDetailsURL = "/DataSnap/rest/TServerMethods1/LookupOrdersPos";
String ordersDetailsAddressesURL = "/DataSnap/rest/TServerMethods1/LookupOrdersAddress";
public String serverURL;
//String serverURL = "http://10.10.10.75:8081";
String username = "admin";
String password = "admin";
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddressesURL() {
return addressesURL;
}
public void setAddressesURL(String addressesURL) {
this.addressesURL = addressesURL;
}
public String getArticlesURL() {
return articlesURL;
}
public void setArticlesURL(String articlesURL) {
this.articlesURL = articlesURL;
}
public String getInvoicesURL() {
return invoicesURL;
}
public void setInvoicesURL(String invoicesURL) {
this.invoicesURL = invoicesURL;
}
public String getInvoicesDetailsURL() {
return invoicesDetailsURL;
}
public void setInvoicesDetailsURL(String invoicesDetailsURL) {
this.invoicesDetailsURL = invoicesDetailsURL;
}
public String getInvoicesDetailsAddressesURL() {
return invoicesDetailsAddressesURL;
}
public void setInvoicesDetailsAddressesURL(String invoicesDetailsAddressesURL) {
this.invoicesDetailsAddressesURL = invoicesDetailsAddressesURL;
}
public String getOrdersURL() {
return ordersURL;
}
public void setOrdersURL(String ordersURL) {
this.ordersURL = ordersURL;
}
public String getOrdersDetailsURL() {
return ordersDetailsURL;
}
public void setOrdersDetailsURL(String ordersDetailsURL) {
this.ordersDetailsURL = ordersDetailsURL;
}
public String getOrdersDetailsAddressesURL() {
return ordersDetailsAddressesURL;
}
public void setOrdersDetailsAddressesURL(String ordersDetailsAddressesURL) {
this.ordersDetailsAddressesURL = ordersDetailsAddressesURL;
}
public String getServerURL() {
return serverURL;
}
public void setServerURL(String serverURL) {
this.serverURL = serverURL;
}}
2nd one is where I start my login Activity
public class Settings extends AppCompatActivity {
//declarations
//Edittext fields for username , server, password & port information
EditText edtIpurl, edtPort, edtUsername, edtPassword;
//Textviews that can be clicked
TextView databaseDel, databaseRef, magnumgmbh, contact, support;
//imagebuttons for bottom menu
ImageButton contacts, articles, invoices, orders;
//string for server URL
//String sURL = "http://";
Thread newSettingsThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
setTitle("Settings");
newSettingsThread = new Thread(){
public void run(){
runOnUiThread(new Runnable() {
#Override
public void run() {
String serverURL = "http://rest.magnumgmbh.de";
//edtIpurl = (EditText)findViewById(R.id.edtIpurl);
Data newD = new Data();
newD.setServerURL(serverURL);
}
});
}
};
newSettingsThread.start();
//start activitys if bottom buttons clicked
contacts = (ImageButton) findViewById(R.id.contacts);
//articles activity start
contacts.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//start activity addresses
Intent startAddresses = new Intent(Settings.this, Addresses.class);
startActivity(startAddresses);
}
});
}}
And the next one is where i try to get my new serverURL
public class Address extends AppCompatActivity{
Thread newAddressThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addresses);
//set activity name
setTitle("Addresses");
//new thread for network operations
newAddressesThread = new Thread() {
public void run() {
//make text from json
jsonText = new StringBuilder();
try {
String str;
Data newData = new Data();
//json dates url
String addressesURL = newData.getAddressesURL();
String serverUrl = newData.getServerURL();
String username = newData.getUsername();
String password = newData.getPassword();
URL url = new URL(serverUrl + addressesURL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//String encoded = Base64.encode("admin:admin");
String encoded = Base64.encodeToString((username+":"+password).getBytes("UTF-8"), Base64.NO_WRAP);
urlConnection.setRequestProperty("Authorization", "Basic " + encoded);
//check http status code
try {
int statusCode = urlConnection.getResponseCode();
System.out.println(statusCode);
} catch (IOException e) {
}
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
while ((str = in.readLine()) != null) {
jsonText.append(str);
}
//cast stringbuilder to string
addressesJsonStr = jsonText.toString();
//close IOstream
in.close();
} catch (MalformedURLException e1) {
System.out.println(e1.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
};
//start thread
newAddressesThread.start();
}}
Hier in the third one by serverURL I got null and it thow me an exeption "Protocol not found: null/DataSnap/rest/TServerMethods1/LookupCustomers" so that is my problem.
What do I wrong?
you are creating a new Object in the third class, so the url has the initilize value because the url you've setted in the second class is stored in another object.
If you want that all Objects of Type Data have the same adress, make the variable static otherwise you have to access the object you have created in the second class in the third class.
I would like to combine two separate parsed jsonObjects into a single arraylist, then display the results as Strings?
I would like to store summaryJsonObject & segment in storylineData. When I step through the code using the debugger summaryJsonObject & segment both hold the raw json. The raw json data also shows in the logcat but storylineData remains null & unavailable throughout.
Here is the parsing code.
public class StorylineData {
private static String date;
private ArrayList<SummaryData> summary;
private ArrayList<SegmentData> segments;
private String caloriesIdle;
private String lastUpdate;
public String getDate() {
return date;
}
public ArrayList<SummaryData> getSummary() {
return summary;
}
public ArrayList<SegmentData> getSegments() {
return segments;
}
public String getCaloriesIdle() {
return caloriesIdle;
}
public String getLastUpdate() {
return lastUpdate;
}
public void setDate(String date) {
this.date = date;
}
public void setSummary(ArrayList<SummaryData> summary) {
this.summary = summary;
}
public void setSegments(ArrayList<SegmentData> segments) {
this.segments = segments;
}
public void setCaloriesIdle(String caloriesIdle) {
this.caloriesIdle = caloriesIdle;
}
public void setLastUpdate(String lastUpdate) {
this.lastUpdate = lastUpdate;
}
public static StorylineData parse(JSONObject jsonObject) {
if (jsonObject != null) {
StorylineData storylineData = new StorylineData();
storylineData.date = jsonObject.optString("date");
storylineData.caloriesIdle = jsonObject.optString("caloriesIdle");
storylineData.lastUpdate = jsonObject.optString("lastUpdate");
storylineData.summary = new ArrayList<SummaryData>();
storylineData.segments = new ArrayList<SegmentData>();
JSONArray summariesJsonArray= jsonObject.optJSONArray("summary");
if (summariesJsonArray != null) {
for (int i = 0; i < summariesJsonArray.length(); i++) {
JSONObject summaryJsonObject = summariesJsonArray.optJSONObject(i);
if (summaryJsonObject != null) {
storylineData.summary.add(SummaryData.parse(summaryJsonObject));
Log.d("storylineHandler", summaryJsonObject.toString());
}
}
}
JSONArray segmentsJsonArray = jsonObject.optJSONArray("segments");
if (segmentsJsonArray != null) {
for (int i = 0; i < segmentsJsonArray.length(); i++) {
JSONObject segment = segmentsJsonArray.optJSONObject(i);
if (segment != null) {
storylineData.segments.add(SegmentData.parse(segment));
Log.d("storylineHandler", segment.toString());
}
}
}
return storylineData;
}
return null;
}
}
The MainActivity looks like this:
MainActivity
public class MainActivity extends FragmentActivity implements OnClickListener{
..other variables here..
List<StorylineData> storylineData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...other ui elements here...
mEditTextResponse = (TextView) findViewById(R.id.editResponse);
storylineData = new StorylineData();
MovesAPI.init(this, CLIENT_ID, CLIENT_SECRET, CLIENT_SCOPES.....
#Override
public void onClick(View v) {
toggleProgress(true);
switch (mSpinnerAPI.getSelectedItemPosition()) {
... other cases here...
break;
...other cases here...
case 4: // Get Summary Day
MovesAPI.getSummary_SingleDay(summaryHandler, "20150418", null);//Date changed to "20150117"
break;
Other cases here..
case 10: // Get Storyline Day
MovesAPI.getStoryline_SingleDay(storylineHandler, "20150418", null, false);//Date changed to "20150418"
break;
...Other cases here..
}
}
... Other MovesHandlers here...
private JSONObject summaryJsonObject;
private List<StorylineData> storylineList;
private JSONObject summariesJsonArray;
private MovesHandler<ArrayList<StorylineData>> storylineHandler = new MovesHandler<ArrayList<StorylineData>>() {
#Override
public void onSuccess(ArrayList<StorylineData> result) {
toggleProgress(false);
storylineList = (List<StorylineData>) StorylineData.parse(summaryJsonObject);
updateResponse( + storylineData.toString() + "\n" //displays true to layout view
result.add(StorylineData.parse(summariesJsonArray))+ "\n"
+Log.d("call result", result.toString()) + "\n" //displays 60 in layout view & com.protogeo.moves.demos.apps.storyline.StorylineData#52824f88, null]
+ Log.d("Log.d storylineHandler", storylineHandler.toString()) + "\n" ); //returns 78 in layout view & com.protogeo.moves.demos.apps.Mainactivity#234234 to log cat
onFailure code here..
}
};
public void toggleProgress(final boolean isProgrressing) {
togglePregress code here..
}
public void updateResponse(final String message) {
runOnUiThread(new Runnable() {
public List<StorylineData> storylineList;
#Override
public void run() {
mEditTextResponse.setText(message);
if (storylineData!= null) {
for (StorylineData storylineData : storylineList) {
mEditTextResponse.append(("storylineData" + storylineData.toString()));
}
}
}
});
}
}
HttpClass
public static void getDailyStorylineList(final MovesHandler<JSONArray> handler,
final String specificSummary,
final String from,
final String to,
final String pastDays,
final String updatedSince,
final boolean needTrackPoints) {
new Thread(new Runnable() {
#Override
public void run() {
try {
/* Refresh access token if only AuthData.MOVES_REFRESHBEFORE days are there to expire current token */
AuthData.refreshAccessTokenIfNeeded();
/* Exchange the authorization code we obtained after login to get access token */
HashMap<String, String> nameValuePairs = new HashMap<String, String>();
nameValuePairs.put("access_token", AuthData.getAuthData().getAccessToken());
// if (specificSummary != null && specificSummary.length() > 0) nameValuePairs.put("specificSummary", specificSummary);//att
if (from != null && from.length() > 0) nameValuePairs.put("from", from);
if (to != null && to.length() > 0) nameValuePairs.put("to", to);
if (pastDays != null && pastDays.length() > 0) nameValuePairs.put("pastDays", pastDays);
if (updatedSince != null && updatedSince.length() > 0) nameValuePairs.put("updatedSince", updatedSince);
if (needTrackPoints) nameValuePairs.put("trackPoints", "true");
URL url = new URL(MovesAPI.API_BASE + MovesAPI.API_PATH_STORYLINE + (specificSummary != null ? specificSummary : "") + "?" + Utilities.encodeUrl(nameValuePairs));
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);
urlConnection.connect();
if (urlConnection.getResponseCode() != 200) {
/* All other HTTP errors from Moves will fall here */
handler.onFailure(getErrorStatus(Utilities.readStream(urlConnection.getErrorStream()), urlConnection.getResponseCode()), "Server not responded with success ("+ urlConnection.getResponseCode() +")");
return;
}
String response = Utilities.readStream(urlConnection.getInputStream());
Object object = new JSONTokener(response).nextValue();
if (object instanceof JSONArray) {
JSONArray jsonArray = (JSONArray) object;
ArrayList<StorylineData> storylineData = new ArrayList<StorylineData>();
if (jsonArray != null) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject storylineJsonObject = jsonArray.optJSONObject(i);
if (storylineJsonObject != null) {
storylineData.add(StorylineData.parse(storylineJsonObject));
}
}
}
handler.onSuccess(storylineData);
} else {
handler.onFailure(MovesStatus.INVALID_RESPONSE, "Expected a JSONArray from server, but failed");
}
} catch (Exception ex) {
ex.printStackTrace();
handler.onFailure(MovesStatus.UNEXPECTED_ERROR, "An unexpected error occured, please check logcat");
}
}
}).start();
}
MovesHandler
public interface MovesHandler<T> {//T stands for generic type
/**
* Implement this method to get success notifications along with the result
* #param result : Result of the operation completed with this handler
*/
public void onSuccess(ProfileData result);
/**
* Implement this method to get failure notifications along with the {#link MovesStatus} code and a brief message
* #param status : Status code of the failure
* #param message : A brief message about the reason behind failure
*/
public void onFailure(MovesStatus status, String message);
}
If you wanted to have one ArrayList to store both SummaryData and SegmentData, you could just created an ArrayList of Objects, ArrayList<Object>. This would be the more general solution.
The alternative would be having SummaryData and SegmentData inherit the same class or implement the same interface.
Using an extended class, you could have:
class Data {
}
class SegmentData extends Data {
}
class SummaryData extends Data {
}
You could then have an ArrayList that would be able to add both SegmentData and SummaryData objects.
If you wanted to show each item as a String you would need to loop through the list and call the toString() function of each item
ArrayList<Data> dataList;
for (Data d : dataList) {
Log.d("data", d.toString())
}
Just make sure to overwrite the toString() function in SegmentData and SummaryData
EDIT: Showing how to print JsonArray
If you wanted to just print for JsonArrays, you could:
public class StorylineData {
private static String date;
private JSONArray summary;
private JSONArray segments;
private String caloriesIdle;
private String lastUpdate;
public String getDate() {
return date;
}
public JSONArray getSummary() {
return summary;
}
public JSONArray getSegments() {
return segments;
}
public String getCaloriesIdle() {
return caloriesIdle;
}
public String getLastUpdate() {
return lastUpdate;
}
public void setDate(String date) {
this.date = date;
}
public void setSummary(JSONArray summary) {
this.summary = summary;
}
public void setSegments(JSONArray segments) {
this.segments = segments;
}
public void setCaloriesIdle(String caloriesIdle) {
this.caloriesIdle = caloriesIdle;
}
public void setLastUpdate(String lastUpdate) {
this.lastUpdate = lastUpdate;
}
public static StorylineData parse(JSONObject jsonObject) {
if (jsonObject != null) {
StorylineData storylineData = new StorylineData();
storylineData.date = jsonObject.optString("date");
storylineData.caloriesIdle = jsonObject.optString("caloriesIdle");
storylineData.lastUpdate = jsonObject.optString("lastUpdate");
storylineData.summary = jsonObject.optJSONArray("summary");
storylineData.segments = jsonObject.optJSONArray("segments");
return storylineData;
}
return null;
}
#Override
public String toString() {
JSONArray combined = new JSONArray(summary);
combined.put(segment);
return combined.toString();
}
}
In your MainActivity
private StorylineData storylineData;
private MovesHandler<JSONArray> storylineHandler = new MovesHandler<JSONArray>() {
#Override
public void onSuccess(JSONArray result) {
toggleProgress(false);
storylineData = StorylineData.parse(summaryJsonObject);
updateResponse(storylineData.toString()) //displays true to layout view
result.add(storylineData.getSummary());
Log.d("call result", result.toString());
Log.d("Log.d storylineHandler", storylineHandler.toString());
}
};
It is necessary to attach a 0313 XEP (0.2)
http://xmpp.org/extensions/attic/xep-0313-0.2.html#sect-idp616432
in to SMACK/ASMACK.
I create PacketExtension for this.
public class Archive313 implements PacketExtension {
static final public String NAMESPACE = "urn:xmpp:mam:tmp";
static final public String ELEMENT = "result";
private String Id;
private String Queryid;
private String Stamp;
private String To;
private String From;
private String Type;
private String Body;
public Archive313(String id, String queryid, String stamp, String to, String from, String type, String body) {
Id = id;
Queryid = queryid;
Stamp = stamp;
To = to;
From = from;
Type = type;
Body = body;
}
#Override
public String getElementName() {
return ELEMENT;
}
#Override
public String getNamespace() {
return NAMESPACE;
}
#Override
public String toXML() {
return "<" + ELEMENT + " xmlns='" + NAMESPACE + "' queryid='" + Queryid + "' id='" + Id + "'>" +
"<forwarded xmlns='urn:xmpp:forward:0'>" +
"<delay xmlns='urn:xmpp:delay' stamp='" + Stamp + "'/><message to='"
+ To + "' from='" + From + "' type='" + Type + "'><body>" + Body + "</body></message></forwarded></result>";
}
public static class Archive313Provider implements PacketExtensionProvider {
#Override
public PacketExtension parseExtension(XmlPullParser xmlPullParser) throws Exception {
String tag_name = "";
String id = "";
String queryid = "";
String stamp = "";
String to = "";
String from = "";
String type = "";
String body = "";
while (xmlPullParser.getEventType() != XmlPullParser.END_DOCUMENT) {
switch (xmlPullParser.getEventType()) {
case XmlPullParser.START_TAG:
tag_name = xmlPullParser.getName();
for (int i = 0; i < xmlPullParser.getAttributeCount(); i++) {
if (tag_name != null && tag_name.equals("result")) {
if (xmlPullParser.getAttributeName(i).equals("queryid")) {
queryid = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("id")) {
id = xmlPullParser.getAttributeValue(i);
}
}
if (tag_name != null && tag_name.equals("delay")) {
if (xmlPullParser.getAttributeName(i).equals("stamp")) {
stamp = xmlPullParser.getAttributeValue(i);
}
}
if (tag_name != null && tag_name.equals("message") && xmlPullParser.getAttributeCount() > 2) {
if (xmlPullParser.getAttributeName(i).equals("to")) {
to = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("from")) {
from = xmlPullParser.getAttributeValue(i);
}
if (xmlPullParser.getAttributeName(i).equals("type")) {
type = xmlPullParser.getAttributeValue(i);
}
}
}
break;
case XmlPullParser.END_TAG:
tag_name = xmlPullParser.getName();
break;
case XmlPullParser.TEXT:
if ("body".equals(tag_name)) {
body = xmlPullParser.getText();
}
break;
default:
break;
}
xmlPullParser.next();
}
return new Archive313(id,queryid,stamp,to,from,type,body);
}
}
}
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("result", "urn:xmpp:mam:tmp", new Archive313.Archive313Provider());
mXMPPConnection.addPacketListener(archiveListener, new PacketExtensionFilter("result", "urn:xmpp:mam:tmp"));
private PacketListener archiveListener = new PacketListener() {
#Override
public void processPacket(Packet packet) {
Log.d("archiveListener", packet.toXML());
}
};
In this implementation I do not give any Packet to archiveListener.
If i set filter:
PacketFilter filter = new PacketFilter() {
#Override
public boolean accept(Packet packet) {
if (packet.toXML().contains("urn:xmpp:mam:tmp")) {
return true;
}
return false;
}
};
I got packages but they are not full.
Need to be:
<message id='aeb213' to='juliet#capulet.lit/chamber'>
<result xmlns='urn:xmpp:mam:tmp' queryid='f27' id='28482-98726-73623'>
<forwarded xmlns='urn:xmpp:forward:0'>
<delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
<message to='juliet#capulet.lit/balcony'
from='romeo#montague.lit/orchard'
type='chat'>
<body>Call me but love, and I'll be new baptized; Henceforth I never will be Romeo.</body>
</message>
</forwarded>
</result>
</message>
I got:
<message id='aeb213' to='juliet#capulet.lit/chamber'>
<result xmlns='urn:xmpp:mam:tmp' queryid='f27' id='28482-98726-73623'>
</result>
</message>
In SMACK Logs I got full message.
It looks like your code
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("result", "urn:xmpp:mam:tmp", new Archive313.Archive313Provider());
never calls. Check this. Commonly, this code must be placed in static block of main class which working with xmpp lib.
To add any extension you have to do three things.
Create a custom extension class extending Extension/ExtensionElement.
Create an extension provider extending ExtensionProvider.
Add custom extension provider to provider manager.
Note : Extension provider will parse your extension from packet (XML) as per your requirement (onParse() method of provider). Every custom extension have to parsed manually and need to add custom provider to provider manager.
Has anyone an idea about what is wrong with my attempt to call a method from a C# dll in my Java code?
Here is my example:
Java code:
public class CsDllHandler {
public interface IKeywordRun extends Library {
public String KeywordRun(String action, String xpath, String inputData,
String verifyData);
}
private static IKeywordRun jnaInstance = null;
public void runDllMethod(String action, String xpath, String inputData,
String verifyData) {
NativeLibrary.addSearchPath(${projectDllName},
"${projectPath}/bin/x64/Debug");
jnaInstance = (IKeywordRun) Native.loadLibrary(
${projectDllName}, IKeywordRun.class);
String csResult = jnaInstance.KeywordRun(action, xpath, inputData,
verifyData);
System.out.println(csResult);
}
}
And in C#:
[RGiesecke.DllExport.DllExport]
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
return "C# here";
}
The Unmanaged Exports nuget should be enough for me to call this method (in theory) but I have some strange error:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invokeString(Function.java:651)
at com.sun.jna.Function.invoke(Function.java:395)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.KeywordRun(Unknown Source)
at auto.test.keywords.utils.CsDllHandler.runDllMethod(CsDllHandler.java:34)
at auto.test.keywords.runner.MainClass.main(MainClass.java:24)
Well, after another day of research and "trial and error" I have found the cause of my problem and a solution.
The cause was that my C# dll had a dependency on log4net.dll. For running a static method from a standalone C# dll the code from the question is all you need.
The solution for using C# dll with dependencies is to create another dll with no dependency and to load the original dll in this adapter with reflection. In Java you should load the adapter dll with jna and call any exported method. I was able not only to execute methods from the adapter but also to configure log4net with reflection and Java
Here is my code:
(C#)
public class CSharpDllHandler {
private static Logger log = Logger.getLogger(CSharpDllHandler.class);
public interface IFrameworkAdapter extends Library {
public String runKeyword(String action, String xpath, String inputData,
String verifyData);
public String configureLog4net(String log4netConfigPath);
public String loadAssemblies(String frameworkDllPath,
String log4netDllPath);
}
private static IFrameworkAdapter jnaAdapterInstance = null;
private String jnaSearchPath = null;
public CSharpDllHandler(String searchPath) {
this.jnaSearchPath = searchPath;
// add to JNA search path
System.setProperty("jna.library.path", jnaSearchPath);
// load attempt
jnaAdapterInstance = (IFrameworkAdapter) Native.loadLibrary(
"FrameworkAdapter", IFrameworkAdapter.class);
}
public String loadAssemblies(String frameworkDllPath, String log4netDllPath) {
String csResult = jnaAdapterInstance.loadAssemblies(frameworkDllPath,
log4netDllPath);
log.debug(csResult);
return csResult;
}
public String runKeyword(String action, String xpath, String inputData,
String verifyData) {
String csResult = jnaAdapterInstance.runKeyword(action, xpath,
inputData, verifyData);
log.debug(csResult);
return csResult;
}
public String configureLogging(String log4netConfigPath) {
String csResult = jnaAdapterInstance
.configureLog4net(log4netConfigPath);
log.debug(csResult);
return csResult;
}
public String getJnaSearchPath() {
return jnaSearchPath;
}
}
In the main method just use something like this:
CSharpDllHandler dllHandler = new CSharpDllHandler(
${yourFrameworkAdapterDllLocation});
dllHandler.loadAssemblies(
${yourOriginalDllPath},${pathToTheUsedLog4netDllFile});
dllHandler.configureLogging(${log4net.config file path});
dllHandler.runKeyword("JAVA Action", "JAVA Xpath", "JAVA INPUT",
"JAVA VERIFY");
dllHandler.runKeyword("JAVA Action2", "JAVA Xpath2", "JAVA INPUT2",
"JAVA VERIFY2");
In C# I have the desired methods on the original dll:
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
log.Debug("Action = " + action);
log.Debug("Xpath = " + xpath);
log.Debug("InputData = " + inputData);
log.Debug("VerifyData = " + verifyData);
return "C# UserActions result: "+ action+" "+xpath+" "+inputData+" "+verifyData;
}
and all the magic is in the DLL Adapter:
namespace FrameworkAdapter {
[ComVisible(true)]
public class FwAdapter {
private const String OK="OK";
private const String frameworkEntryClassName = "${nameOfTheDllClass with method to run }";
private const String log4netConfiguratorClassName = "log4net.Config.XmlConfigurator";
private static Assembly frameworkDll = null;
private static Type frameworkEntryClass = null;
private static MethodInfo keywordRunMethod = null;
private static Assembly logDll = null;
private static Type logEntryClass = null;
private static MethodInfo logConfigureMethod = null;
private static String errorMessage = "OK";
[RGiesecke.DllExport.DllExport]
public static string loadAssemblies(string frameworkDllPath, string log4netDllPath) {
try {
errorMessage = LoadFrameworkDll(frameworkDllPath, frameworkEntryClassName);
LoadFrameworkMethods("KeywordRun", "Setup", "TearDown");
errorMessage = LoadLogAssembly(log4netDllPath, log4netConfiguratorClassName);
if (errorMessage.CompareTo(OK) == 0)
errorMessage = LoadLogMethods("Configure");
}
catch (Exception e) {
return e.Message;
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string configureLog4net(string log4netConfigPath) {
if (errorMessage.CompareTo("OK") == 0) {
StringBuilder sb = new StringBuilder();
sb.AppendLine("Try to configure Log4Net");
try {
FileInfo logConfig = new FileInfo(log4netConfigPath);
logConfigureMethod.Invoke(null, new object[] { logConfig });
sb.AppendLine("Log4Net configured");
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string runKeyword(string action, string xpath, string inputData, string verifyData) {
StringBuilder sb = new StringBuilder();
object result = null;
try {
result = keywordRunMethod.Invoke(null, new object[] { action, xpath, inputData, verifyData });
sb.AppendLine(result.ToString());
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
private static String LoadFrameworkDll(String dllFolderPath, String entryClassName) {
try {
frameworkDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = frameworkDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
frameworkEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogAssembly(String dllFolderPath, String entryClassName) {
try {
logDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = logDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
logEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogMethods(String logMethodName) {
try {
logConfigureMethod = logEntryClass.GetMethod(logMethodName, new Type[] { typeof(FileInfo) });
}
catch (Exception e) {
return e.Message;
}
return OK;
}
private static void LoadFrameworkMethods(String keywordRunName, String scenarioSetupName, String scenarioTearDownName) {
///TODO load the rest of the desired methods here
keywordRunMethod = frameworkEntryClass.GetMethod(keywordRunName);
}
}
}
Running this code will provide all the logged messages from the original C# DLL to the Java console output (and to a file if configured). In a similar way, we can load any other needed dll files for runtime.
Please forgive my [very probable wrong] way of doing things in C# with reflection, I'm new to this language.