Source Code Cross Referenced for SOAPMessageImpl.java in  » Web-Services-AXIS2 » saaj » org » apache » axis2 » saaj » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Services AXIS2 » saaj » org.apache.axis2.saaj 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one
003:         * or more contributor license agreements. See the NOTICE file
004:         * distributed with this work for additional information
005:         * regarding copyright ownership. The ASF licenses this file
006:         * to you under the Apache License, Version 2.0 (the
007:         * "License"); you may not use this file except in compliance
008:         * with the License. You may obtain a copy of the License at
009:         *
010:         * http://www.apache.org/licenses/LICENSE-2.0
011:         *
012:         * Unless required by applicable law or agreed to in writing,
013:         * software distributed under the License is distributed on an
014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015:         * KIND, either express or implied. See the License for the
016:         * specific language governing permissions and limitations
017:         * under the License.
018:         */
019:        package org.apache.axis2.saaj;
020:
021:        import org.apache.axiom.om.OMOutputFormat;
022:        import org.apache.axiom.soap.impl.dom.soap11.SOAP11Factory;
023:        import org.apache.axiom.soap.impl.dom.soap12.SOAP12Factory;
024:        import org.apache.axis2.transport.http.HTTPConstants;
025:
026:        import javax.xml.soap.AttachmentPart;
027:        import javax.xml.soap.MimeHeader;
028:        import javax.xml.soap.MimeHeaders;
029:        import javax.xml.soap.SOAPBody;
030:        import javax.xml.soap.SOAPElement;
031:        import javax.xml.soap.SOAPException;
032:        import javax.xml.soap.SOAPHeader;
033:        import javax.xml.soap.SOAPMessage;
034:        import javax.xml.soap.SOAPPart;
035:        import java.io.IOException;
036:        import java.io.InputStream;
037:        import java.io.OutputStream;
038:        import java.util.ArrayList;
039:        import java.util.Collection;
040:        import java.util.Hashtable;
041:        import java.util.Iterator;
042:        import java.util.Map;
043:
044:        public class SOAPMessageImpl extends SOAPMessage {
045:
046:            private SOAPPart soapPart;
047:            private Collection attachmentParts = new ArrayList();
048:            private MimeHeadersEx mimeHeaders;
049:
050:            private Map props = new Hashtable();
051:            private boolean saveRequired;
052:
053:            public SOAPMessageImpl(SOAPEnvelopeImpl soapEnvelope) {
054:                String contentType = null;
055:
056:                if (mimeHeaders != null) {
057:                    String contentTypes[] = mimeHeaders
058:                            .getHeader(HTTPConstants.CONTENT_TYPE);
059:                    contentType = (contentTypes != null) ? contentTypes[0]
060:                            : null;
061:                } else {
062:                    this .mimeHeaders = new MimeHeadersEx();
063:                    if (soapEnvelope.getOMFactory() instanceof  SOAP11Factory) {
064:                        contentType = HTTPConstants.MEDIA_TYPE_TEXT_XML;
065:                        this .mimeHeaders.addHeader("content-type", contentType);
066:                    } else if (soapEnvelope.getOMFactory() instanceof  SOAP12Factory) {
067:                        contentType = HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML;
068:                        this .mimeHeaders.addHeader("content-type", contentType);
069:                    }
070:                }
071:
072:                setCharsetEncoding(contentType);
073:                soapPart = new SOAPPartImpl(this , soapEnvelope);
074:            }
075:
076:            public SOAPMessageImpl(InputStream inputstream,
077:                    javax.xml.soap.MimeHeaders mimeHeaders)
078:                    throws SOAPException {
079:                String contentType = null;
080:                String tmpContentType = "";
081:                if (mimeHeaders != null) {
082:                    String contentTypes[] = mimeHeaders
083:                            .getHeader(HTTPConstants.CONTENT_TYPE);
084:                    if (contentTypes != null && contentTypes.length > 0) {
085:                        tmpContentType = contentTypes[0];
086:                        //tmpContentType can be like 'application/soap+xml; charset=UTF-8;'
087:                        //Only the first part is important
088:                        if (tmpContentType.indexOf(";") > -1) {
089:                            contentType = tmpContentType.substring(0,
090:                                    tmpContentType.indexOf(";"));
091:                        } else {
092:                            contentType = tmpContentType;
093:                        }
094:                    }
095:                }
096:                //Setting the whole content-type string to CharsetEncoding.
097:                //Is this correct?
098:                setCharsetEncoding(tmpContentType);
099:                if (contentType != null) {
100:                    soapPart = new SOAPPartImpl(this , inputstream, mimeHeaders);
101:                } else {
102:                    soapPart = new SOAPPartImpl(this , inputstream);
103:                }
104:
105:                this .mimeHeaders = (mimeHeaders == null) ? new MimeHeadersEx()
106:                        : new MimeHeadersEx(mimeHeaders);
107:            }
108:
109:            /**
110:             * Retrieves a description of this <CODE>SOAPMessage</CODE> object's content.
111:             *
112:             * @return a <CODE>String</CODE> describing the content of this message or <CODE>null</CODE> if
113:             *         no description has been set
114:             * @see #setContentDescription(String) setContentDescription(java.lang.String)
115:             */
116:            public String getContentDescription() {
117:                String values[] = mimeHeaders
118:                        .getHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION);
119:                if (values != null && values.length > 0) {
120:                    return values[0];
121:                }
122:                return null;
123:            }
124:
125:            /**
126:             * Sets the description of this <CODE>SOAPMessage</CODE> object's content with the given
127:             * description.
128:             *
129:             * @param description a <CODE>String</CODE> describing the content of this message
130:             * @see #getContentDescription() getContentDescription()
131:             */
132:            public void setContentDescription(String description) {
133:                mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION,
134:                        description);
135:            }
136:
137:            /**
138:             * Gets the SOAP part of this <CODE>SOAPMessage</CODE> object.
139:             * <p/>
140:             * <p/>
141:             * <P>If a <CODE>SOAPMessage</CODE> object contains one or more attachments, the SOAP Part must
142:             * be the first MIME body part in the message.</P>
143:             *
144:             * @return the <CODE>SOAPPart</CODE> object for this <CODE> SOAPMessage</CODE> object
145:             */
146:            public SOAPPart getSOAPPart() {
147:                return soapPart;
148:            }
149:
150:            /**
151:             * Removes all <CODE>AttachmentPart</CODE> objects that have been added to this
152:             * <CODE>SOAPMessage</CODE> object.
153:             * <p/>
154:             * <P>This method does not touch the SOAP part.</P>
155:             */
156:            public void removeAllAttachments() {
157:                attachmentParts.clear();
158:            }
159:
160:            /**
161:             * Gets a count of the number of attachments in this message. This count does not include the
162:             * SOAP part.
163:             *
164:             * @return the number of <CODE>AttachmentPart</CODE> objects that are part of this
165:             *         <CODE>SOAPMessage</CODE> object
166:             */
167:            public int countAttachments() {
168:                return attachmentParts.size();
169:            }
170:
171:            /**
172:             * Retrieves all the <CODE>AttachmentPart</CODE> objects that are part of this
173:             * <CODE>SOAPMessage</CODE> object.
174:             *
175:             * @return an iterator over all the attachments in this message
176:             */
177:            public Iterator getAttachments() {
178:                return attachmentParts.iterator();
179:            }
180:
181:            /**
182:             * Retrieves all the AttachmentPart objects that have header entries that match the specified
183:             * headers. Note that a returned attachment could have headers in addition to those specified.
184:             *
185:             * @param headers a {@link javax.xml.soap.MimeHeaders} object containing the MIME headers for
186:             *                which to search
187:             * @return an iterator over all attachments({@link javax.xml.soap.AttachmentPart}) that have a
188:             *         header that matches one of the given headers
189:             */
190:            public Iterator getAttachments(javax.xml.soap.MimeHeaders headers) {
191:                Collection matchingAttachmentParts = new ArrayList();
192:                Iterator iterator = getAttachments();
193:                {
194:                    AttachmentPartImpl part;
195:                    while (iterator.hasNext()) {
196:                        part = (AttachmentPartImpl) iterator.next();
197:                        if (part.matches(headers)) {
198:                            matchingAttachmentParts.add(part);
199:                        }
200:                    }
201:                }
202:                return matchingAttachmentParts.iterator();
203:            }
204:
205:            /**
206:             * Adds the given <CODE>AttachmentPart</CODE> object to this <CODE>SOAPMessage</CODE> object. An
207:             * <CODE> AttachmentPart</CODE> object must be created before it can be added to a message.
208:             *
209:             * @param attachmentPart an <CODE> AttachmentPart</CODE> object that is to become part of this
210:             *                       <CODE>SOAPMessage</CODE> object
211:             * @throws IllegalArgumentException
212:             *
213:             */
214:            public void addAttachmentPart(AttachmentPart attachmentPart) {
215:                if (attachmentPart != null) {
216:                    attachmentParts.add(attachmentPart);
217:                    mimeHeaders.setHeader(HTTPConstants.CONTENT_TYPE,
218:                            "multipart/related");
219:                }
220:            }
221:
222:            /**
223:             * Creates a new empty <CODE>AttachmentPart</CODE> object. Note that the method
224:             * <CODE>addAttachmentPart</CODE> must be called with this new <CODE>AttachmentPart</CODE>
225:             * object as the parameter in order for it to become an attachment to this
226:             * <CODE>SOAPMessage</CODE> object.
227:             *
228:             * @return a new <CODE>AttachmentPart</CODE> object that can be populated and added to this
229:             *         <CODE>SOAPMessage</CODE> object
230:             */
231:            public AttachmentPart createAttachmentPart() {
232:                return new AttachmentPartImpl();
233:            }
234:
235:            /**
236:             * Returns all the transport-specific MIME headers for this <CODE>SOAPMessage</CODE> object in a
237:             * transport-independent fashion.
238:             *
239:             * @return a <CODE>MimeHeaders</CODE> object containing the <CODE>MimeHeader</CODE> objects
240:             */
241:            public javax.xml.soap.MimeHeaders getMimeHeaders() {
242:                return mimeHeaders;
243:            }
244:
245:            /**
246:             * Updates this <CODE>SOAPMessage</CODE> object with all the changes that have been made to it.
247:             * This method is called automatically when a message is sent or written to by the methods
248:             * <CODE>ProviderConnection.send</CODE>, <CODE> SOAPConnection.call</CODE>, or <CODE>
249:             * SOAPMessage.writeTo</CODE>. However, if changes are made to a message that was received or to
250:             * one that has already been sent, the method <CODE>saveChanges</CODE> needs to be called
251:             * explicitly in order to save the changes. The method <CODE>saveChanges</CODE> also generates
252:             * any changes that can be read back (for example, a MessageId in profiles that support a
253:             * message id). All MIME headers in a message that is created for sending purposes are
254:             * guaranteed to have valid values only after <CODE>saveChanges</CODE> has been called.
255:             * <p/>
256:             * <P>In addition, this method marks the point at which the data from all constituent
257:             * <CODE>AttachmentPart</CODE> objects are pulled into the message.</P>
258:             *
259:             * @throws SOAPException if there was a problem saving changes to this message.
260:             */
261:            public void saveChanges() throws SOAPException {
262:                saveRequired = false;
263:                // TODO not sure of the implementation
264:            }
265:
266:            public void setSaveRequired() {
267:                this .saveRequired = true;
268:            }
269:
270:            /**
271:             * Indicates whether this <CODE>SOAPMessage</CODE> object has had the method {@link
272:             * #saveChanges()} called on it.
273:             *
274:             * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has been called on this message at
275:             *         least once; <CODE> false</CODE> otherwise.
276:             */
277:            public boolean saveRequired() {
278:                return saveRequired;
279:            }
280:
281:            /**
282:             * Writes this <CODE>SOAPMessage</CODE> object to the given output stream. The externalization
283:             * format is as defined by the SOAP 1.1 with Attachments specification.
284:             * <p/>
285:             * <P>If there are no attachments, just an XML stream is written out. For those messages that
286:             * have attachments, <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
287:             *
288:             * @param out the <CODE>OutputStream</CODE> object to which this <CODE>SOAPMessage</CODE> object
289:             *            will be written
290:             * @throws SOAPException if there was a problem in externalizing this SOAP message
291:             * @throws IOException   if an I/O error occurs
292:             */
293:            public void writeTo(OutputStream out) throws SOAPException,
294:                    IOException {
295:                try {
296:                    OMOutputFormat format = new OMOutputFormat();
297:                    format
298:                            .setCharSetEncoding((String) getProperty(CHARACTER_SET_ENCODING));
299:                    String writeXmlDecl = (String) getProperty(WRITE_XML_DECLARATION);
300:                    if (writeXmlDecl == null || writeXmlDecl.equals("false")) {
301:
302:                        //SAAJ default case doesn't send XML decl
303:                        format.setIgnoreXMLDeclaration(true);
304:                    }
305:
306:                    //the writeTo method forces the elements to be built!!!
307:                    ((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMEnvelope()
308:                            .serialize(out, format);
309:                    saveChanges();
310:                } catch (Exception e) {
311:                    throw new SOAPException(e);
312:                }
313:            }
314:
315:            /**
316:             * Associates the specified value with the specified property. If there was already a value
317:             * associated with this property, the old value is replaced.
318:             * <p/>
319:             * The valid property names include <code>WRITE_XML_DECLARATION</code> and
320:             * <code>CHARACTER_SET_ENCODING</code>. All of these standard SAAJ properties are prefixed by
321:             * "javax.xml.soap". Vendors may also add implementation specific properties. These properties
322:             * must be prefixed with package names that are unique to the vendor.
323:             * <p/>
324:             * Setting the property <code>WRITE_XML_DECLARATION</code> to <code>"true"</code> will cause an
325:             * XML Declaration to be written out at the start of the SOAP message. The default value of
326:             * "false" suppresses this declaration.
327:             * <p/>
328:             * The property <code>CHARACTER_SET_ENCODING</code> defaults to the value <code>"utf-8"</code>
329:             * which causes the SOAP message to be encoded using UTF-8. Setting
330:             * <code>CHARACTER_SET_ENCODING</code> to <code>"utf-16"</code> causes the SOAP message to be
331:             * encoded using UTF-16.
332:             * <p/>
333:             * Some implementations may allow encodings in addition to UTF-8 and UTF-16. Refer to your
334:             * vendor's documentation for details.
335:             *
336:             * @param property the property with which the specified value is to be associated
337:             * @param value    the value to be associated with the specified property
338:             */
339:            public void setProperty(String property, Object value) {
340:                props.put(property, value);
341:            }
342:
343:            /**
344:             * Retrieves value of the specified property.
345:             *
346:             * @param property the name of the property to retrieve
347:             * @return the value of the property or <code>null</code> if no such property exists
348:             * @throws SOAPException if the property name is not recognized
349:             */
350:            public Object getProperty(String property) throws SOAPException {
351:                return props.get(property);
352:            }
353:
354:            /**
355:             * Returns an AttachmentPart object that is associated with an attachment that is referenced by
356:             * this SOAPElement or null if no such attachment exists. References can be made via an href
357:             * attribute as described in SOAP Messages with Attachments (http://www.w3.org/TR/SOAPattachments#SOAPReferenceToAttachements)
358:             * , or via a single Text child node containing a URI as described in the WS-I Attachments
359:             * Profile 1.0 for elements of schema type ref:swaRef(ref:swaRef (http://www.wsi.org/Profiles/AttachmentsProfile-1.0-2004-08-24.html")
360:             * ). These two mechanisms must be supported. The support for references via href attribute also
361:             * implies that this method should also be supported on an element that is an xop:Include
362:             * element (XOP (http://www.w3.org/2000/xp/Group/3/06/Attachments/XOP.html) ). other reference
363:             * mechanisms may be supported by individual implementations of this standard. Contact your
364:             * vendor for details.
365:             *
366:             * @param element - The SOAPElement containing the reference to an Attachment
367:             * @return the referenced AttachmentPart or null if no such AttachmentPart exists or no
368:             *         reference can be found in this SOAPElement.
369:             * @throws SOAPException - if there is an error in the attempt to access the attachment
370:             */
371:            public AttachmentPart getAttachment(SOAPElement soapelement)
372:                    throws SOAPException {
373:                //TODO read strings from constants
374:                Iterator iterator = getAttachments();
375:                {
376:                    AttachmentPartImpl attachmentPart;
377:                    while (iterator.hasNext()) {
378:                        attachmentPart = (AttachmentPartImpl) iterator.next();
379:                        String[] contentIds = attachmentPart
380:                                .getMimeHeader("Content-Id");
381:
382:                        //References can be made via an href attribute as described in SOAP Messages
383:                        //with Attachments or via a single Text child node containing a URI
384:                        String reference = soapelement.getAttribute("href");
385:                        if (reference == null || reference.trim().length() == 0) {
386:                            reference = soapelement.getValue();
387:                            if (reference == null
388:                                    || reference.trim().length() == 0) {
389:                                return null;
390:                            }
391:                        }
392:
393:                        for (int a = 0; a < contentIds.length; a++) {
394:                            //eg: cid:gifImage scenario
395:                            String idPart = reference.substring(reference
396:                                    .indexOf(":") + 1);
397:                            idPart = "<" + idPart + ">";
398:                            if (idPart.equals(contentIds[a])) {
399:                                return attachmentPart;
400:                            }
401:                        }
402:
403:                        String[] contentLocations = attachmentPart
404:                                .getMimeHeader("Content-Location");
405:                        if (!(contentLocations == null)) {
406:                            //uri scenario
407:                            for (int b = 0; b < contentLocations.length; b++) {
408:                                if (reference.equals(contentLocations[b])) {
409:                                    return attachmentPart;
410:                                }
411:                            }
412:                        }
413:                    }
414:                }
415:                return null;
416:            }
417:
418:            /**
419:             * Removes all the AttachmentPart objects that have header entries that match the specified
420:             * headers. Note that the removed attachment could have headers in addition to those specified.
421:             *
422:             * @param headers - a MimeHeaders object containing the MIME headers for which to search
423:             * @since SAAJ 1.3
424:             */
425:            public void removeAttachments(MimeHeaders headers) {
426:                Collection newAttachmentParts = new ArrayList();
427:                Iterator attachmentPartsItr = attachmentParts.iterator();
428:                for (Iterator iter = attachmentPartsItr; iter.hasNext();) {
429:                    AttachmentPart attachmentPart = (AttachmentPart) iter
430:                            .next();
431:
432:                    //Get all the headers
433:                    Iterator allMIMEHeaders = headers.getAllHeaders();
434:                    for (Iterator iterator = allMIMEHeaders; iterator.hasNext();) {
435:                        MimeHeader mimeHeader = (MimeHeader) iterator.next();
436:                        String[] headerValues = attachmentPart
437:                                .getMimeHeader(mimeHeader.getName());
438:                        //if values for this header name, do not remove it
439:                        if (headerValues.length != 0) {
440:                            if (!(headerValues[0].equals(mimeHeader.getValue()))) {
441:                                newAttachmentParts.add(attachmentPart);
442:                            }
443:                        }
444:                    }
445:                }
446:                attachmentParts.clear();
447:                this .attachmentParts = newAttachmentParts;
448:            }
449:
450:            /**
451:             * Gets the SOAP Header contained in this <code>SOAPMessage</code> object.
452:             *
453:             * @return the <code>SOAPHeader</code> object contained by this <code>SOAPMessage</code> object
454:             * @throws javax.xml.soap.SOAPException if the SOAP Header does not exist or cannot be
455:             *                                      retrieved
456:             */
457:            public SOAPHeader getSOAPHeader() throws SOAPException {
458:                return this .soapPart.getEnvelope().getHeader();
459:            }
460:
461:            /**
462:             * Gets the SOAP Body contained in this <code>SOAPMessage</code> object.
463:             *
464:             * @return the <code>SOAPBody</code> object contained by this <code>SOAPMessage</code> object
465:             * @throws javax.xml.soap.SOAPException if the SOAP Body does not exist or cannot be retrieved
466:             */
467:            public SOAPBody getSOAPBody() throws SOAPException {
468:                return this .soapPart.getEnvelope().getBody();
469:            }
470:
471:            /**
472:             * Set the character encoding based on the <code>contentType</code> parameter
473:             *
474:             * @param contentType
475:             */
476:            private void setCharsetEncoding(final String contentType) {
477:                if (contentType != null) {
478:                    int delimiterIndex = contentType.lastIndexOf("charset");
479:                    if (delimiterIndex > 0) {
480:                        String charsetPart = contentType
481:                                .substring(delimiterIndex);
482:                        int charsetIndex = charsetPart.indexOf('=');
483:                        String charset = charsetPart
484:                                .substring(charsetIndex + 1).trim();
485:                        if ((charset.startsWith("\"") || charset
486:                                .startsWith("\'"))) {
487:                            charset = charset.substring(1, charset.length());
488:                        }
489:                        if ((charset.endsWith("\"") || charset.endsWith("\'"))) {
490:                            charset = charset
491:                                    .substring(0, charset.length() - 1);
492:                        }
493:                        int index = charset.indexOf(';');
494:                        if (index != -1) {
495:                            charset = charset.substring(0, index);
496:                        }
497:                        setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
498:                    }
499:                }
500:            }
501:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.