Mercurial > hg > mpdl-group
view software/eXist/mpdl-modules/src/de/mpg/mpiwg/berlin/mpdl/xmlrpc/MpdlXmlRpcInterfaceImpl.java @ 0:408254cf2f1d
Erstellung
author | Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de> |
---|---|
date | Wed, 24 Nov 2010 17:24:23 +0100 |
parents | |
children |
line wrap: on
line source
package de.mpg.mpiwg.berlin.mpdl.xmlrpc; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import de.mpg.mpiwg.berlin.mpdl.exception.ApplicationException; public class MpdlXmlRpcInterfaceImpl implements MpdlXmlRpcInterface { private static MpdlXmlRpcInterfaceImpl instance; private static Logger LOGGER = Logger.getLogger(MpdlXmlRpcInterfaceImpl.class); // Logs to EXIST_HOME/webapp/WEB-INF/logs/exist.log private String serverName = "localhost"; private int port = 8090; private String xmlRpcUri = "http://" + serverName + ":" + port + "/exist/xmlrpc"; private XmlRpcClient xmlClient = null; private String userName = "admin"; private String pw = ""; private MpdlXmlRpcInterfaceImpl() { } public static MpdlXmlRpcInterfaceImpl getInstance(String serverName, int port, String userName, String pw) throws ApplicationException { if (instance == null) { instance = new MpdlXmlRpcInterfaceImpl(); } instance.serverName = serverName; instance.port = port; instance.userName = userName; instance.pw = pw; instance.xmlRpcUri = "http://" + serverName + ":" + port + "/exist/xmlrpc"; instance.init(); return instance; } public String[] getDocumentNames(String collection) throws ApplicationException { String[] documentNames = null; try { Object[] params = new Object[1]; params[0] = collection; HashMap collectionDesc = (HashMap) xmlClient.execute("getCollectionDesc", params); Object[] documents = (Object[]) collectionDesc.get("documents"); documentNames = new String[documents.length]; for (int i=0; i < documents.length; i++) { HashMap doc = (HashMap) documents[i]; String docName = (String) doc.get("name"); documentNames[i] = collection + "/" + docName; } } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } return documentNames; } public boolean readDocumentIntoLocalFile(String collection, String documentName, String localFileName) throws ApplicationException { boolean success = false; OutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(localFileName)); Hashtable options = new Hashtable(); options.put("indent", "yes"); options.put("encoding", "UTF-8"); options.put("expand-xincludes", "yes"); options.put("highlight-matches", "elements"); // get the document from eXist Object[] params = new Object[2]; params[0] = collection + "/" + documentName; params[1] = options; HashMap result = (HashMap) xmlClient.execute("getDocumentData", params); byte[] data = (byte[]) result.get("data"); String handle = (String) result.get("handle"); Integer offset = (Integer) result.get("offset"); out.write(data); // the first chunk of data // if there are more than one chunk of data while (offset != 0) { Object[] paramsGetNextChunk = new Object[2]; paramsGetNextChunk[0] = handle; paramsGetNextChunk[1] = offset; HashMap resultChunk = (HashMap) xmlClient.execute("getNextChunk", paramsGetNextChunk); data = (byte[]) resultChunk.get("data"); out.write(data); offset = (Integer) resultChunk.get("offset"); } out.flush(); success = true; } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } catch (IOException e) { logError(e); throw new ApplicationException(e); } finally { try { if (out != null) out.close(); } catch (Exception e) { // nothing: always close the stream at the end of the method } } return success; } public boolean saveDocument(String collection, String documentName, String localFile) throws ApplicationException { boolean success = false; String mimeType = getMimeType(localFile); // e.g. text/xml or application/xml ... try { testFile(localFile); // first: create an empty file on server byte[] dummyChunk = new byte[0]; Object[] paramsUpload1 = new Object[2]; paramsUpload1[0] = dummyChunk; paramsUpload1[1] = 0; String tmpFileNameOnServer = (String) xmlClient.execute("upload", paramsUpload1); // second: upload the whole file in chunks to server file; normally needs 3 seconds for 20 MB int chunkSize = 20000 * 1024; // copies data from a file in 20 MB chunks to server file so that not too much RAM is consumed on server InputStream localFileInputStream = new BufferedInputStream(new FileInputStream(localFile)); byte[] chunk = new byte[chunkSize]; while ((chunk = readBytes(localFileInputStream, chunkSize)) != null) { int realChunkSize = chunk.length; // is smaller than chunkSize if last chunk is read Object[] paramsUpload2 = new Object[3]; paramsUpload2[0] = tmpFileNameOnServer; paramsUpload2[1] = chunk; paramsUpload2[2] = realChunkSize; String uploadResult = (String) xmlClient.execute("upload", paramsUpload2); } // third: parseLocal String docName = collection + "/" + documentName; Object[] paramsParseLocal = new Object[4]; paramsParseLocal[0] = tmpFileNameOnServer; paramsParseLocal[1] = docName; paramsParseLocal[2] = true; // overwrites an existing file of the same name if it exists paramsParseLocal[3] = mimeType; // mime type of the document success = (Boolean) xmlClient.execute("parseLocal", paramsParseLocal); } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } catch (FileNotFoundException e) { logError(e); throw new ApplicationException(e); } return success; } public boolean saveDocuments(String collection, String localFileDirectory) throws ApplicationException { boolean success = true; testFile(localFileDirectory); // directory exists ? File localFileDir = new File(localFileDirectory); File[] files = localFileDir.listFiles(); for (int i=0; i < files.length; i++) { File f = files[i]; String fileNameWithoutPath = f.getName(); String localFileName = f.getPath(); boolean localSuccess = saveDocument(collection, fileNameWithoutPath, localFileName); if (! localSuccess) success = false; } return success; } public boolean saveDocuments(String collection, String localFileDirectory, String fileExtension) throws ApplicationException { boolean success = true; testFile(localFileDirectory); // directory exists ? File localFileDir = new File(localFileDirectory); FilenameFilter filter = new FilenameFilterExtension(fileExtension); File[] files = localFileDir.listFiles(filter); for (int i=0; i < files.length; i++) { File f = files[i]; String fileNameWithoutPath = f.getName(); String localFileName = f.getPath(); boolean localSuccess = saveDocument(collection, fileNameWithoutPath, localFileName); if (! localSuccess) success = false; } return success; } public boolean deleteDocument(String collection, String documentName) throws ApplicationException { boolean success = false; String[] docDesc = getDocumentDescription(collection, documentName); if (docDesc == null) { // document does not exist System.out.println("Warning: Could not delete: " + collection + "/" + documentName + " because it does not exist"); } else { success = deleteDocument(collection + "/" + documentName); } return success; } public boolean deleteDocuments(String collection) throws ApplicationException { boolean success = true; String[] documentNames = getDocumentNames(collection); for (int i=0; i < documentNames.length; i++) { String documentName = documentNames[i]; boolean localSuccess = deleteDocument(documentName); if (! localSuccess) success = false; } return success; } public boolean createCollection(String collection) throws ApplicationException { boolean success = false; try { Object[] params = new Object[1]; params[0] = collection; success = (Boolean) xmlClient.execute("createCollection", params); } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } return success; } public boolean deleteCollection(String collection) throws ApplicationException { boolean success = false; try { Object[] params = new Object[1]; params[0] = collection; success = (Boolean) xmlClient.execute("removeCollection", params); } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } return success; } private void init() throws ApplicationException { try { XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); config.setServerURL(new URL(xmlRpcUri)); config.setBasicUserName(userName); config.setBasicPassword(pw); xmlClient = new XmlRpcClient(); xmlClient.setConfig(config); } catch (MalformedURLException e) { logError(e); throw new ApplicationException(e); } } private void logError(Exception e) { LOGGER.error(e.getMessage()); LOGGER.error(e.getStackTrace()); } private String[] getDocumentDescription(String collection, String documentName) throws ApplicationException { String[] documentDesc = new String[3]; try { Object[] params = new Object[1]; params[0] = collection + "/" + documentName; HashMap docDesc = (HashMap) xmlClient.execute("describeResource", params); if (docDesc == null || docDesc.isEmpty()) return null; String name = (String) docDesc.get("name"); String owner = (String) docDesc.get("owner"); String group = (String) docDesc.get("group"); documentDesc[0] = name; documentDesc[1] = owner; documentDesc[2] = group; } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } return documentDesc; } private boolean deleteDocument(String fullDocumentName) throws ApplicationException { boolean success = false; try { Object[] params = new Object[1]; params[0] = fullDocumentName; success = (Boolean) xmlClient.execute("remove", params); } catch (XmlRpcException e) { logError(e); throw new ApplicationException(e); } return success; } private void testFile(String fileName) throws ApplicationException { File file = new File(fileName); boolean fileExists = file.exists(); if (! fileExists) { throw new ApplicationException("File: " + fileName + " does not exist"); } } /** * Reads a chunk of data of an input stream. * Does not close the stream until last bytes are read * @in in the input stream to be read * @chunkSize chunkSize length of the chunk which is read * @return byte[] of bytes read */ private byte[] readBytes(InputStream in, int chunkSize) throws ApplicationException { byte[] resultBytes = new byte[chunkSize]; try { int len = in.read(resultBytes, 0, chunkSize); if (len == -1) { try { in.close(); } catch (Exception e) { } // close the stream if end of file is reached resultBytes = null; } else if (len < chunkSize && len != chunkSize) { // if read chunk is last chunk of the file it delivers this chunk byte[] tmp = new byte[len]; System.arraycopy(resultBytes, 0, tmp, 0, len); resultBytes = tmp; } } catch (FileNotFoundException e) { logError(e); throw new ApplicationException(e); } catch (IOException e) { logError(e); throw new ApplicationException(e); } return resultBytes; } /** * Reads a file storing intermediate data into an array. * @file file the file to be read * @return byte[] of file content */ private byte[] readAllBytes(String file) throws ApplicationException { InputStream in = null; byte[] out = new byte[0]; try { in = new BufferedInputStream(new FileInputStream(file)); // the length of a buffer can vary int bufLen = 20000*1024; byte[] buf = new byte[bufLen]; byte[] tmp = null; int len = 0; while((len = in.read(buf, 0, bufLen)) != -1) { // extend array tmp = new byte[out.length + len]; System.arraycopy(out, 0, tmp, 0, out.length); System.arraycopy(buf, 0, tmp, out.length, len); out = tmp; tmp = null; } } catch (FileNotFoundException e) { logError(e); throw new ApplicationException(e); } catch (IOException e) { logError(e); throw new ApplicationException(e); } finally { // always close the stream if (in != null) try { in.close(); } catch (Exception e) { } } return out; } private String getMimeType(String fileName) throws ApplicationException { String mimeType = null; File file = new File(fileName); try { URI uri = file.toURI(); URL url = uri.toURL(); URLConnection urlConnection = url.openConnection(); mimeType = urlConnection.getContentType(); } catch (MalformedURLException e) { logError(e); throw new ApplicationException(e); } catch (IOException e) { logError(e); throw new ApplicationException(e); } return mimeType; } /** * Reads a file storing intermediate data into an array. * @file file the file to be read * @return byte array of the file content * TODO test this method if it is really faster */ private byte[] readAllBytesFast(String file) throws ApplicationException { InputStream in = null; byte[] buf = null; int bufLen = 20000*1024; try { in = new BufferedInputStream(new FileInputStream(file)); buf = new byte[bufLen]; byte[] tmp = null; int len = 0; List data = new ArrayList(24); // keeps peaces of data while((len = in.read(buf, 0, bufLen)) != -1){ tmp = new byte[len]; System.arraycopy(buf, 0, tmp, 0, len); // still need to do copy data.add(tmp); } /* This part os optional. This method could return a List data for further processing, etc. */ len = 0; if (data.size() == 1) return (byte[]) data.get(0); for (int i=0;i<data.size();i++) len += ((byte[]) data.get(i)).length; buf = new byte[len]; // final output buffer len = 0; for (int i=0;i<data.size();i++){ // fill with data tmp = (byte[]) data.get(i); System.arraycopy(tmp,0,buf,len,tmp.length); len += tmp.length; } } catch (FileNotFoundException e) { logError(e); throw new ApplicationException(e); } catch (IOException e) { logError(e); throw new ApplicationException(e); } finally { if (in != null) try { in.close(); } catch (Exception e) {} } return buf; } }