/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. 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. */ package com.esri.gpt.migration.to1; import java.io.IOException; import java.io.StringReader; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.sql.Timestamp; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.esri.gpt.catalog.arcims.ImsServiceException; import com.esri.gpt.framework.http.CredentialProvider; import com.esri.gpt.framework.http.HttpClientRequest; import com.esri.gpt.framework.http.StringHandler; import com.esri.gpt.framework.http.StringProvider; import com.esri.gpt.framework.http.HttpClientRequest.MethodName; import com.esri.gpt.framework.util.UuidUtil; import com.esri.gpt.framework.util.Val; import com.esri.gpt.framework.xml.XmlIoUtil; /** * Retrieves a document executing a request against an ArcIMS metadata publish service. */ public class RemoteGetDocumentRequest extends DefaultHandler { // class variables ============================================================= // instance variables ========================================================== private String _thumbnailUrl = ""; private Timestamp _updateDate = null; private String _uuid = ""; private String _xml = ""; private String _xmlUrl = ""; private String _userName = ""; private String _password = ""; private String _serviceUrl = ""; private StringBuffer _characters = new StringBuffer(); // constructors ================================================================ /** * Constructor * @param serviceUrl the arcims metadata service http endpoint * @param userName the arcims metadata service username * @param password the arcims metadata service password */ public RemoteGetDocumentRequest(String serviceUrl, String userName, String password) { _userName = userName; _password = password; _serviceUrl = serviceUrl; } // properties ================================================================== /** * Gets the url to the thumbnail image. * @return the thumbnail url */ private String getThumbnailUrl() { return _thumbnailUrl; } /** * Sets the url to the thumbnail image. * @param url the thumbnail url */ private void setThumbnailUrl(String url) { _thumbnailUrl = Val.chkStr(url); } /** * Gets the update date. * @return the update date */ public Timestamp getUpdateDate() { return _updateDate; } /** * Sets the update date. * @param updateDate the update date */ private void setUpdateDate(String updateDate) { updateDate = Val.chkStr(updateDate); if (updateDate.length() == 0) { _updateDate = null; } else { try { _updateDate = Timestamp.valueOf(updateDate); } catch (Exception e) { _updateDate = null; System.err.println("Error setting update date: " + updateDate); e.printStackTrace(System.err); } } } /** * Sets the update date. * @param updateDate the update date */ protected void setUpdateTimestamp(Timestamp updateDate) { _updateDate = updateDate; } /** * Gets the document uuid. * @return the document uuid */ public String getUuid() { return _uuid; } /** * Sets the document uuid * @param uuid the document uuid */ private void setUuid(String uuid) { _uuid = UuidUtil.addCurlies(uuid); } /** * Gets the url to the xml document. * @return the url to the xml document */ private String getXmlUrl() { return _xmlUrl; } /** * Sets the url to the xml document. * @param url the xml document url */ private void setXmlUrl(String url) { _xmlUrl = Val.chkStr(url); } /** * Gets the document xml. * @return the document xml */ public String getXml() { return _xml; } /** * Sets the document xml. * @param xml the document xml */ protected void setXml(String xml) { _xml = Val.chkStr(xml); } // methods ===================================================================== /** * Executes a GET_METADATA_DOCUMENT request against an ArcIMS metadata publish service. * @param docUuid the metatata document uuid of the record to load * @throws Exception * @throws PublishServiceException if an exception occurs */ public void executeGet(String docUuid) throws Exception { reset(); setUuid(docUuid); // make the axl request StringBuffer sbAxl = new StringBuffer(); sbAxl = new StringBuffer(); sbAxl.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sbAxl.append("\r\n<ARCXML version=\"1.1\">"); sbAxl.append("\r\n<REQUEST>"); sbAxl.append("\r\n<GET_METADATA>"); sbAxl.append("\r\n<GET_METADATA_DOCUMENT docid=\"").append(getUuid()).append("\"/>"); sbAxl.append("\r\n</GET_METADATA>"); sbAxl.append("\r\n</REQUEST>"); sbAxl.append("\r\n</ARCXML>"); // setAxlRequest(sbAxl.toString()); // execute the request, read the XML file // UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(_userName, _password); CredentialProvider provider = new CredentialProvider(_userName, _password); executeRequest(provider,_serviceUrl,sbAxl.toString()); /* if (wasActionOK()) { if (getXmlUrl().length() > 0) { setXml(XmlIoUtil.readXml(getXmlUrl())); } }*/ } /** * Executes an ArcIMS service request and parses the response. * @throws Exception */ protected void executeRequest(CredentialProvider provider, String serviceUrl,String requestBody) throws Exception { // setActionStatus(ACTION_STATUS_NONE); // setAxlResponse(""); String sMsg; String sErrPfx = "ArcIMS Service Communication Error: "; HttpClientRequest httpClient = new HttpClientRequest(); // send the request try { httpClient.setCredentialProvider(provider); httpClient.setUrl(serviceUrl); // httpClient.setTimeoutMillisecs(service.getTimeoutMillisecs()); httpClient.setMethodName(MethodName.POST); // httpClient.setAxlRequest(getAxlRequest()); StringProvider cprov = new StringProvider(requestBody,"text/xml"); httpClient.setContentProvider(cprov); StringHandler sh = new StringHandler(); httpClient.setContentHandler(sh); httpClient.execute(); // setAxlResponse(httpClient.getAxlResponse()); int nHttpResponseCode = httpClient.getResponseInfo().getResponseCode(); if ((nHttpResponseCode < 200) || (nHttpResponseCode > 299)) { throw new IOException("Request failed: HTTP "+nHttpResponseCode); } } catch (MalformedURLException em) { // setActionStatus(ACTION_STATUS_ERROR); sMsg = sErrPfx+"The PublishServer was configured with a malformed URL"; throw new ImsServiceException(sMsg,em); } catch (UnknownHostException eu) { // setActionStatus(ACTION_STATUS_ERROR); sMsg = sErrPfx+"The PublishServer was configured with an unknown host"; throw new ImsServiceException(sMsg,eu); } catch (Exception e) { // setActionStatus(ACTION_STATUS_ERROR); int nHttpResponseCode = httpClient.getResponseInfo().getResponseCode(); if (nHttpResponseCode == 0) { sMsg = Val.chkStr(e.getMessage()); sMsg = sErrPfx+sMsg; throw new ImsServiceException(sMsg,e); } else { sMsg = sErrPfx+"[HTTP "+nHttpResponseCode+"] "+httpClient.getResponseInfo().getResponseMessage(); throw new ImsServiceException(sMsg,e); } } String response = httpClient.readResponseAsCharacters(); // parse the response if (response.length() == 0) { throw new Exception(sErrPfx+"Empty response."); } else { /*int start = response.indexOf("<!--"); int end = response.indexOf("-->"); response = response.substring(start,end); */ parseAxlResponse(response); if (getXmlUrl().length() > 0) { setXml(XmlIoUtil.readXml(getXmlUrl())); } } } /** * Starts a SAX parser on an ArcIMS axl response. * @param axlResponse the ArcIMS axl response * @throws ParserConfigurationException if the exception occurs * @throws SAXException if the exception occurs * @throws IOException if the exception occurs */ protected void parseAxlResponse(String axlResponse) throws ParserConfigurationException, SAXException, IOException { SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); InputSource src = new InputSource(new StringReader(axlResponse)); parser.parse(src,this); } /** * Triggered when a SAX element is started during the parsing of an axl response. * @param lowerCaseTagName the lower-case tag name of the element * @param attributes the element attributes */ protected void onStartSaxElement(String lowerCaseTagName, Attributes attributes) { if (lowerCaseTagName.equals("metadata_dataset")) { setXmlUrl(attributes.getValue("url")); setThumbnailUrl(attributes.getValue("thumbnail")); setUpdateDate(attributes.getValue("updated")); } } /** * Resets the request. */ public void reset() { setUuid(""); setXml(""); setXmlUrl(""); setThumbnailUrl(""); setUpdateDate(null); } /** * Sets text node characters for a SAX element. * @param ch the array of characters * @param start the starting position within the array * @param length the number of characters to read from the array * @throws SAXException if the exception occurs */ @Override public void characters(char ch[], int start, int length) throws SAXException { if ((ch != null) && (length > 0)) _characters.append(ch,start,length); } /** * Ends a SAX element. * <br/>The parser is not namespace aware. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @throws SAXException if a SAXException occurs */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { String sTag = returnLowerCaseTag(uri,localName,qName); String sCharacters = _characters.toString().trim(); // check for errors if (sTag.equals("error")) { throw new SAXException(sCharacters); } else if (sCharacters.startsWith("[ERR")) { throw new SAXException(sCharacters); } // trigger end element, reset characters onEndSaxElement(sTag,sCharacters); _characters = new StringBuffer(); } /** * Triggered when a SAX element is ended during the parsing of an axl response. * @param lowerCaseTagName the lower-case tag name of the element * @param characters the text node value of the element */ protected void onEndSaxElement(String lowerCaseTagName, String characters) { if (lowerCaseTagName.equals("uuid")) { setUuid(characters); } } /** * Returns the lower case tag name for an element. * <br/>The parser is not namespace aware. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @return the lower case tag name */ private String returnLowerCaseTag(String uri, String localName, String qName) { if (qName == null) { return ""; } else { return qName.trim().toLowerCase(); } } /** * Starts a SAX element. * <br/>The parser is not namespace aware. * @param uri the uri namespace for the element * @param localName the local name for the element * @param qName the qualified name for the element * @param attributes the attributes for the element * @throws SAXException if a SAXException occurs */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // reset characters, trigger start element _characters = new StringBuffer(); String sTag = returnLowerCaseTag(uri,localName,qName); onStartSaxElement(sTag,attributes); } }