package nsf.playground.snippets; import java.io.File; import java.lang.reflect.Array; import java.util.List; import java.util.Properties; import java.util.Vector; import javax.faces.application.FacesMessage; import lotus.domino.Database; import lotus.domino.Document; import lotus.domino.View; import nsf.playground.jobs.AsyncAction; import com.ibm.commons.Platform; import com.ibm.commons.util.StringUtil; import com.ibm.sbt.playground.assets.Asset; import com.ibm.sbt.playground.assets.AssetBrowser; import com.ibm.sbt.playground.assets.AssetNode; import com.ibm.sbt.playground.assets.CategoryNode; import com.ibm.sbt.playground.assets.Node; import com.ibm.sbt.playground.assets.NodeFactory; import com.ibm.sbt.playground.assets.RootNode; import com.ibm.sbt.playground.vfs.FileVFS; import com.ibm.sbt.playground.vfs.GitVFS; import com.ibm.sbt.playground.vfs.VFS; import com.ibm.sbt.playground.vfs.VFSFile; import com.ibm.xsp.FacesExceptionEx; import com.ibm.xsp.context.FacesContextEx; /** * Base class for importing assets. * * @author priand * */ public abstract class AssetImporter { public static AssetImporter createImporter(String type, Database db) { if(StringUtil.equals(type, JavaScriptSnippetImporter.TYPE)) { return new JavaScriptSnippetImporter(db); } else if(StringUtil.equals(type, JavaSnippetImporter.TYPE)) { return new JavaSnippetImporter(db); } else if(StringUtil.equals(type, XPagesSnippetImporter.TYPE)) { return new XPagesSnippetImporter(db); } else if(StringUtil.equals(type, GadgetSnippetImporter.TYPE)) { return new GadgetSnippetImporter(db); } else if(StringUtil.equals(type, APIImporter.TYPE)) { return new APIImporter(db); } return null; } private Database db; public AssetImporter(Database db) { this.db = db; } public Database getDatabase() { return db; } // // Methods to be implemented by the concrete classes // // "html", "api"... protected abstract String getAssetType(); protected abstract String getAssetForm(); protected abstract NodeFactory getNodeFactory(); protected abstract void saveAsset(ImportSource source, VFSFile root, AssetNode node, Asset asset) throws Exception; //////////////////////////////////////////////////////////////////////////////// // // Import sources management // //////////////////////////////////////////////////////////////////////////////// protected ImportSource getSource(String type, String srcName) throws Exception { return loadSource(type,srcName); } protected ImportSource loadSource(String type, String srcName) throws Exception { View v = db.getView("AllImportSourcesByType"); try { Vector<Object> keys = new Vector<Object>(); keys.add(type); keys.add(srcName); Document doc = v.getDocumentByKey(keys); try { if(doc!=null) { return loadSource(doc); } return null; } finally { doc.recycle(); } } finally { v.recycle(); } } protected ImportSource loadSource(Document document) throws Exception { //String type = document.getItemValueString("Type"); String name = document.getItemValueString("Name"); String source = document.getItemValueString("Source"); String location = document.getItemValueString("Location"); String userName = document.getItemValueString("User"); String password = document.getItemValueString("Password"); String[] runtimes = null; Vector<String> vRuntimes = (Vector<String>)document.getItemValue("Runtimes"); if(vRuntimes!=null && !vRuntimes.isEmpty()) { runtimes = vRuntimes.toArray(new String[vRuntimes.size()]); } ImportSource src = new ImportSource(name,source,location,userName,password,runtimes); return src; } protected int importAssets(ImportSource source, VFSFile root, Node node, final AsyncAction action) throws Exception { int count=0; if(node.isCategory()) { CategoryNode cn=(CategoryNode) node; // Browse recursively... List<Node> children=cn.getChildren(); for(Node n : children) { count+=importAssets(source, root, n, action); } } else if(node.isAsset()) { if(action!=null) { action.updateTask(StringUtil.format("Importing Asset: {0}", node.getPath())); } Asset asset = loadAsset(source, root, (AssetNode) node); if(asset!=null && shouldImport(asset)) { saveAsset(source, root, (AssetNode)node, asset); count++; } } return count; } protected Asset loadAsset(ImportSource source, VFSFile root, AssetNode node) throws Exception { return node.load(root); } protected boolean shouldImport(Asset asset) { String pub = asset.getProperty("publish"); if(StringUtil.equals(pub, "false")) { return false; } return true; } //////////////////////////////////////////////////////////////////////////////// // // Import action // //////////////////////////////////////////////////////////////////////////////// public void importAssets(String sourceName, AsyncAction action) throws Exception { try { ImportSource source = getSource(getAssetType(),sourceName); if(action!=null) { action.updateTask("Deleting assets"); } deleteAssets(source,action); if(action!=null) { if(action.isCancelled()) { return; } action.updateCompletion(100,50); action.updateTask("Importing assets"); } int count = importAssets(source,action); String msg = StringUtil.format("{0} assets successfully imported from source {1}", count, sourceName); if(action!=null) { action.updateCompletion(100,100); action.updateTask(msg); } FacesContextEx ctx = FacesContextEx.getCurrentInstance(); if(ctx!=null) { FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); FacesContextEx.getCurrentInstance().addMessage(null, m); } } catch(Exception ex) { String msg = StringUtil.format("Error while importing assets from source \"{0}\"", sourceName); FacesContextEx ctx = FacesContextEx.getCurrentInstance(); if(ctx!=null) { FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); FacesContextEx.getCurrentInstance().addMessage(null, m); } Platform.getInstance().log(ex); if(action!=null) { action.updateException(ex,msg); } } } protected int importAssets(ImportSource source, final AsyncAction action) throws Exception { VFS vfs=createImportVFS(source); VFSFile rootDir=vfs.getRoot(); AssetBrowser a=new AssetBrowser(rootDir, getNodeFactory()) { // Import all the nodes to the DB, regardless of the constraints (endpoints, jslibs...) protected boolean includeNode(Properties properties){ return true; } }; AssetBrowser.Callback cb=null; if(action!=null) { cb=new AssetBrowser.Callback() { public void update(String statusString) { action.updateTask(statusString); } public boolean isCancelled() { return action.isCancelled(); } }; } RootNode root=a.readAssets(cb); if(action!=null&&action.isCancelled()) { return 0; } return importAssets(source, rootDir, root, action); } protected VFS createImportVFS(ImportSource source) { if(StringUtil.equals(source.getSource(), "file")) { String location=source.getLocation().trim(); File baseDir=new File(location); if(!baseDir.exists()) { throw new FacesExceptionEx(null, "Import directory {0} does not exist", location); } FileVFS vfs=new FileVFS(baseDir); return vfs; } else if(StringUtil.equals(source.getSource(), "github")) { String location=source.getLocation().trim(); if(StringUtil.isEmpty(location)) { throw new FacesExceptionEx(null, "GitHub: Location is empty", location); } GitVFS vfs=new GitVFS(location, source.getUserName(), source.getPassword()); return vfs; } throw new FacesExceptionEx(null, "Import action is not available for a source type {0}", source.getSource()); } //////////////////////////////////////////////////////////////////////////////// // // Delete action // //////////////////////////////////////////////////////////////////////////////// public void deleteAssets(String sourceName) throws Exception { try { ImportSource source = getSource(getAssetType(),sourceName); deleteAssets(source,null); String msg = StringUtil.format("Assets successfully deleted from source {0}", sourceName); FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); FacesContextEx.getCurrentInstance().addMessage(null, m); } catch(Exception ex) { Platform.getInstance().log(ex); String msg = StringUtil.format("Error while deleting assets from source {0}", sourceName); FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); FacesContextEx.getCurrentInstance().addMessage(null, m); } } protected void deleteAssets(ImportSource source, AsyncAction action) throws Exception { View v = db.getView("AllSnippetsByImportSource"); try { Vector key = new Vector(); key.add(getAssetForm()); key.add(source.getName()); v.getAllEntriesByKey(key).removeAll(true); } finally { v.recycle(); } } // // Utilities to be used by subclasses // protected void setItemValue(Document doc, String name, Object v) throws Exception { if(v==null) { return; } Object dominoValue=toDominoType(v); doc.replaceItemValue(name, dominoValue); } protected void setItemValueRichText(Document doc, String name, String v) throws Exception { setItemValue(doc, name, v); // if(v==null) { // return; // } // RichTextItem rti = doc.createRichTextItem(name); // rti.appendText(v); } protected void setItemValues(Document doc, String name, String value) throws Exception { if(StringUtil.isNotEmpty(value)) { String[] t = StringUtil.splitString(value, ','); setItemValue(doc, name, t); } } protected Object toDominoType(Object v) throws Exception { if(v.getClass().isArray()) { int length=Array.getLength(v); if(length>0) { Vector<Object> vec=new Vector<Object>(length); for(int i=0; i<length; i++) { vec.add(toDominoType(Array.get(v, i))); } return vec; } } return v; } }