/*
* Importer.java
*
* Created on September 11, 2007, 9:36 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.tools;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.atomojo.app.client.Entry;
import org.atomojo.app.client.EntryClient;
import org.atomojo.app.client.FeedClient;
import org.atomojo.app.client.FeedDestination;
import org.atomojo.app.client.StatusException;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.XMLException;
import org.restlet.data.MediaType;
import org.restlet.data.Metadata;
import org.restlet.data.Status;
import org.restlet.representation.InputRepresentation;
import org.restlet.service.MetadataService;
/**
*
* @author alex
*/
public class DirectorySynchronizer
{
static class Target {
File dir;
URI feed;
Target(File dir,URI feed)
{
this.dir = dir;
this.feed = feed;
}
}
URI baseFeed;
File directory;
boolean exact;
boolean excludeDot;
Logger log;
String username;
String password;
/** Creates a new instance of Importer */
public DirectorySynchronizer(File directory,URI baseFeed)
{
this.baseFeed = baseFeed;
this.directory = directory;
this.exact = false;
this.log = Logger.getLogger(DirectorySynchronizer.class.getName());
this.excludeDot = false;
this.username = null;
this.password = null;
}
public void setIdentity(String username,String password) {
this.username = username;
this.password = password;
}
public Logger getLogger() {
return log;
}
public void setLogger(Logger log)
{
this.log = log;
}
public void setExact(boolean flag)
{
this.exact = flag;
}
public boolean isExact() {
return this.exact;
}
public void setExcludingDotFiles(boolean flag)
{
this.excludeDot = flag;
}
public boolean isExcludingDotFiles() {
return this.excludeDot;
}
public void setDirectory(File dir)
{
this.directory = dir;
}
public File getDirectory() {
return this.directory;
}
public void sync()
{
final List<Target> targets = new ArrayList<Target>();
targets.add(new Target(directory,baseFeed));
while (targets.size()>0) {
final Target target = targets.remove(0);
log.info("Syncing directory "+target.dir+" with feed "+target.feed);
final FeedClient feedClient = new FeedClient(target.feed);
feedClient.setIdentity(username,password);
if (!feedClient.exists()) {
log.info("Creating feed "+target.feed);
try {
Document doc = InfosetFactory.getDefaultInfoset().createItemConstructor().createDocument();
Element feed = doc.createDocumentElement(FeedClient.FEED_NAME);
Element title = feed.addElement(FeedClient.TITLE_NAME);
title.addCharacters(target.dir.getName());
Status status = feedClient.create(doc);
if (!status.isSuccess()) {
log.log(Level.SEVERE,"Cannot create feed "+target.feed+" due to error "+status.getCode());
continue;
}
} catch (XMLException ex) {
log.log(Level.SEVERE,"Cannot create feed "+target.feed+" due to exception.",ex);
continue;
}
}
final Map<String,Entry> entries = new HashMap<String,Entry>();
try {
feedClient.get(new FeedDestination() {
public void onFeed(Document feedDoc) {}
public void onEntry(Document entryDoc) {
Entry entry = new Entry(entryDoc);
Entry.Media media = entry.getMediaContent();
if (media!=null) {
//log.info("Caching entry for "+media.getName());
entries.put(media.getName(),entry);
}
}
});
} catch (XMLException ex) {
log.log(Level.SEVERE,"Cannot get feed "+target.feed+" due to XML exception.",ex);
continue;
} catch (IOException ex) {
log.log(Level.SEVERE,"Cannot get feed "+target.feed+" due to I/O exception.",ex);
continue;
}
String u = target.feed.toString();
if (u.charAt(u.length()-1)!='/') {
u += "/";
}
final String feedBase = u;
final MetadataService metadataService = new MetadataService();
target.dir.listFiles(new FileFilter() {
public boolean accept(File file) {
if (file.isDirectory()) {
URI subFeed = URI.create(feedBase+file.getName()+"/");
targets.add(new Target(file,subFeed));
} else {
if (!excludeDot || file.getName().charAt(0)!='.') {
// Sync content
Entry entry = entries.get(file.getName());
Status status = null;
if (entry!=null) {
log.info("Updating "+file);
// update existing media
try {
FileInputStream is = new FileInputStream(file);
EntryClient client = feedClient.getEntryClient(entry);
status = client.updateMedia(new InputRepresentation(is,entry.getMediaContent().getMediaType()));
is.close();
} catch (IOException ex) {
log.log(Level.SEVERE,"Cannot update "+file+" due to I/O exception.",ex);
}
entries.remove(file.getName());
} else {
log.info("Creating "+file);
// create new media
try {
FileInputStream is = new FileInputStream(file);
int extPos = file.getName().lastIndexOf('.');
String ext = extPos<0 ? null : file.getName().substring(extPos+1);
Metadata metadata = ext==null ? null : metadataService.getMetadata(ext);
MediaType type = metadata==null ? MediaType.APPLICATION_OCTET_STREAM : MediaType.valueOf(metadata.getName());
Entry mediaEntry = feedClient.createMedia(file.getName(),new InputRepresentation(is,type));
is.close();
} catch (StatusException ex) {
log.log(Level.SEVERE,"Cannot create media entry from "+file+" due to status "+ex.getStatus().getCode(),ex);
} catch (Exception ex) {
log.log(Level.SEVERE,"Cannot create media entry from "+file+" due to exception.",ex);
}
}
if (status!=null && !status.isSuccess()) {
log.severe("Cannot update/create media entry for "+file+" due to status "+status.getCode());
}
}
}
return false;
}
});
if (exact) {
for (Entry entry : entries.values()) {
EntryClient client = feedClient.getEntryClient(entry);
Status status = client.delete();
if (!status.isSuccess()) {
log.severe("Cannot delete extra entry "+entry.getId()+" due to status "+status.getCode());
}
}
}
}
}
}