001: package com.openedit.modules.update;
002:
003: import java.io.File;
004: import java.io.InputStream;
005: import java.io.InputStreamReader;
006: import java.io.OutputStream;
007: import java.io.Reader;
008: import java.net.URLEncoder;
009: import java.text.DateFormat;
010: import java.text.SimpleDateFormat;
011: import java.util.ArrayList;
012: import java.util.Date;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Map;
017:
018: import org.apache.commons.collections.map.ListOrderedMap;
019: import org.apache.commons.httpclient.HttpClient;
020: import org.apache.commons.httpclient.NameValuePair;
021: import org.apache.commons.httpclient.methods.PostMethod;
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.dom4j.DocumentHelper;
025: import org.dom4j.Element;
026:
027: import com.openedit.OpenEditException;
028: import com.openedit.util.XmlUtil;
029: import com.openedit.util.ZipUtil;
030:
031: public class SyncToServer {
032: private static final Log log = LogFactory
033: .getLog(SyncToServer.class);
034: protected HttpClient fieldHttpClient;
035:
036: protected String fieldServerUrl;
037: protected File fieldRoot;
038: protected String fieldUsername;
039: protected String fieldPassword;
040: protected XmlUtil fieldXmlUtils;
041: protected ZipUtil fieldZipUtils;
042: protected DateFormat fieldDateFormat;
043:
044: public String getUsername() {
045: return fieldUsername;
046: }
047:
048: public void setUsername(String inUsername) {
049: fieldUsername = inUsername;
050: }
051:
052: public String getPassword() {
053: return fieldPassword;
054: }
055:
056: public void setPassword(String inPassword) {
057: fieldPassword = inPassword;
058: }
059:
060: public String getServerUrl() {
061: return fieldServerUrl;
062: }
063:
064: public void setServerUrl(String url) {
065: if (!url.startsWith("http://")) {
066: url = "http://" + url;
067: }
068:
069: if (!url.endsWith("/")) {
070: url += "/";
071: }
072: fieldServerUrl = url;
073: }
074:
075: public File getRoot() {
076: return fieldRoot;
077: }
078:
079: public void setRoot(File inRoot) {
080: fieldRoot = inRoot;
081: }
082:
083: public void syncFromServer(String inPath) throws Exception {
084: String url = getServerUrl();
085: log.info("posting here:" + url);
086:
087: url += "openedit/update/sync/listfiles.xml?syncpath=";
088:
089: processPath(url, inPath);
090: }
091:
092: protected void processPath(String inUrl, String inPath)
093: throws Exception {
094: log.info("Process Path " + inUrl + inPath);
095:
096: PostMethod postMethod = new PostMethod(inUrl + inPath);
097:
098: postMethod.addParameter("accountname", getUsername());
099: postMethod.addParameter("password", getPassword());
100:
101: //client.getHttpConnectionManager().getParams().setConnectionTimeout(0);
102: int statusCode1 = getHttpClient().executeMethod(postMethod);
103:
104: //postMethod.releaseConnection(); //Is this needed?
105: if (statusCode1 == 200) {
106: InputStream body = postMethod.getResponseBodyAsStream();
107: Reader reader = new InputStreamReader(body, "UTF-8");
108: Element root = getXmlUtils().getXml(reader, "UTF-8");
109: //Make three lists. Remote, local, remote downloads
110: //loop over files look for dates or time changes
111: compareWithRemote(inUrl, inPath, root);
112: } else {
113: //inReq.putPageValue("message", "Status code: <b>" + statusCode1 + "</b><br>" + postMethod.getResponseBodyAsString() );
114: log.error("Could not get list");
115: throw new OpenEditException("Error getting list: "
116: + statusCode1 + " "
117: + postMethod.getResponseBodyAsString());
118: }
119:
120: }
121:
122: private void compareWithRemote(String inUrl, String inPath,
123: Element root) throws Exception {
124: Map remote = ListOrderedMap.decorate(new HashMap());
125: for (Iterator iterator = root.elementIterator("file"); iterator
126: .hasNext();) {
127: Element file = (Element) iterator.next();
128: remote.put(file.attributeValue("path"), file);
129: }
130:
131: //Set local
132: Map local = buildLocalList(inPath);
133:
134: List allremote = new ArrayList(remote.values());
135: for (Iterator iterator = allremote.iterator(); iterator
136: .hasNext();) {
137: Element remotefile = (Element) iterator.next();
138: String path = remotefile.attributeValue("path");
139: path = path.replaceAll("\\\\", "/");
140: Element localfile = (Element) local.get(path);
141: if (isEquals(remotefile, localfile)) {
142: remote.remove(path); //remove it from the lis of files to download
143: }
144: local.remove(path); //If diferent then remote will replace local anyways
145: }
146: downloadAll(inUrl, remote);
147: deleteExtraFiles(local);
148:
149: //loop over subdirectories calling this method
150: for (Iterator iterator = root.elementIterator("dir"); iterator
151: .hasNext();) {
152: Element dir = (Element) iterator.next();
153: String next = dir.attributeValue("path");
154: next = next.replaceAll("\\\\", "/");
155: processPath(inUrl, next);
156: }
157: }
158:
159: protected void downloadAll(String inUrl, Map inRemote)
160: throws Exception {
161: if (inRemote.size() == 0) {
162: //nothing to download
163: return;
164: }
165: String url = getServerUrl();
166: log.info("posting here:" + url);
167: url += "openedit/update/sync/downloadfiles.zip";
168: PostMethod postMethod = new PostMethod(url);
169:
170: postMethod.addParameter("accountname", getUsername());
171: postMethod.addParameter("password", getPassword());
172:
173: for (Iterator iterator = inRemote.values().iterator(); iterator
174: .hasNext();) {
175: Element file = (Element) iterator.next();
176: postMethod
177: .addParameter("file", file.attributeValue("path"));
178: }
179: //Not sure if this is efficient or not
180:
181: //client.getHttpConnectionManager().getParams().setConnectionTimeout(0);
182: int statusCode1 = getHttpClient().executeMethod(postMethod);
183:
184: if (statusCode1 == 200) {
185: InputStream in = postMethod.getResponseBodyAsStream();
186: getZipUtils().unzip(in, getRoot());
187: //Reset the time stamp for each file
188: for (Iterator iterator = inRemote.values().iterator(); iterator
189: .hasNext();) {
190: Element element = (Element) iterator.next();
191: String dated = element.attributeValue("date");
192: File file = new File(getRoot(), element
193: .attributeValue("path"));
194: Date date = getDateFormat().parse(dated);
195: file.setLastModified(date.getTime());
196: log.info("Saved " + element.attributeValue("path"));
197: }
198:
199: //TODO: Close the stream?
200: }
201: }
202:
203: protected void deleteExtraFiles(Map inLocal) {
204: for (Iterator iterator = inLocal.values().iterator(); iterator
205: .hasNext();) {
206: Element element = (Element) iterator.next();
207: if (element.getName().equals("file")) {
208:
209: File file = new File(getRoot(), element
210: .attributeValue("path"));
211: log.info("deleting " + file.getAbsolutePath());
212: file.delete();
213:
214: }
215:
216: }
217: }
218:
219: protected boolean isEquals(Element inRemotefile, Element inLocalfile) {
220: if (inLocalfile != null) {
221: String date = inRemotefile.attributeValue("date");
222: String date2 = inLocalfile.attributeValue("date");
223: return date.equals(date2);
224: }
225:
226: return false;
227: }
228:
229: public List listLocalFiles(String inPath) throws OpenEditException {
230: Map f = buildLocalList(inPath);
231: return new ArrayList(f.values());
232: }
233:
234: protected Map buildLocalList(String inPath)
235: throws OpenEditException {
236: Map local = ListOrderedMap.decorate(new HashMap());
237: File[] children = new File(getRoot(), inPath).listFiles();
238: if (children != null) {
239: for (int i = 0; i < children.length; i++) {
240: File child = children[i];
241: Element e = null;
242: if (child.isDirectory()) {
243: e = DocumentHelper.createElement("dir");
244: } else {
245: e = DocumentHelper.createElement("file");
246: e.addAttribute("date", getDateFormat().format(
247: new Date(child.lastModified())));
248: }
249: String path = child.getPath();
250:
251: path = path.substring(getRoot().getPath().length());
252: path = path.replaceAll("\\\\", "/");
253: e.addAttribute("path", path);
254: local.put(path, e);
255: }
256: }
257: return local;
258: }
259:
260: public HttpClient getHttpClient() {
261: if (fieldHttpClient == null) {
262: fieldHttpClient = new HttpClient();
263: }
264:
265: return fieldHttpClient;
266: }
267:
268: public void setHttpClient(HttpClient inHttpClient) {
269: fieldHttpClient = inHttpClient;
270: }
271:
272: public XmlUtil getXmlUtils() {
273: if (fieldXmlUtils == null) {
274: fieldXmlUtils = new XmlUtil();
275: }
276:
277: return fieldXmlUtils;
278: }
279:
280: public void setXmlUtils(XmlUtil inUtils) {
281: fieldXmlUtils = inUtils;
282: }
283:
284: public ZipUtil getZipUtils() {
285: if (fieldZipUtils == null) {
286: fieldZipUtils = new ZipUtil();
287: fieldZipUtils.setRoot(getRoot());
288: }
289: return fieldZipUtils;
290: }
291:
292: public void setZipUtils(ZipUtil inZipUtils) {
293: fieldZipUtils = inZipUtils;
294: }
295:
296: public DateFormat getDateFormat() {
297: if (fieldDateFormat == null) {
298: fieldDateFormat = new SimpleDateFormat(
299: "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
300: }
301: return fieldDateFormat;
302: }
303:
304: public void setDateFormat(DateFormat inDateFormat) {
305: fieldDateFormat = inDateFormat;
306: }
307:
308: public void sendFiles(List inPaths, OutputStream inOutputStream)
309: throws Exception {
310: getZipUtils().zipFiles(inPaths, inOutputStream);
311: }
312: }
|