package railo.runtime; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import railo.commons.lang.StringUtil; import railo.runtime.component.ComponentLoader; import railo.runtime.component.MetaDataSoftReference; import railo.runtime.component.MetadataUtil; import railo.runtime.dump.DumpData; import railo.runtime.dump.DumpProperties; import railo.runtime.dump.DumpTable; import railo.runtime.engine.ThreadLocalPageContext; import railo.runtime.exp.PageException; import railo.runtime.type.Array; import railo.runtime.type.ArrayImpl; import railo.runtime.type.Collection; import railo.runtime.type.KeyImpl; import railo.runtime.type.Struct; import railo.runtime.type.StructImpl; import railo.runtime.type.UDF; import railo.runtime.type.UDFImpl; import railo.runtime.type.UDFProperties; import railo.runtime.type.util.ArrayUtil; import railo.runtime.type.util.KeyConstants; /** * * MUST add handling for new attributes (style, namespace, serviceportname, porttypename, wsdlfile, bindingname, and output) */ public class InterfaceImpl implements Interface { private static final long serialVersionUID = -2488865504508636253L; private static final InterfaceImpl[] EMPTY = new InterfaceImpl[]{}; //private InterfacePage page; private PageSource pageSource; private String extend; private String hint; private String dspName; private String callPath; private boolean realPath; private Map meta; private InterfaceImpl[] superInterfaces; private Map<Collection.Key,UDF> udfs=new HashMap<Collection.Key,UDF>(); private Map<Collection.Key,UDF> interfacesUDFs; /** * Constructor of the Component * @param output * @param extend * @param hint * @param dspName */ public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs) { this(page.getPageSource(),extend, hint, dspName,callPath, realPath,interfacesUDFs,null); } public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs, Map meta) { this(page.getPageSource(),extend, hint, dspName,callPath, realPath,interfacesUDFs,meta); } public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs) { this(pageSource, extend, hint, dspName, callPath, realPath, interfacesUDFs, null); } public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean realPath,Map interfacesUDFs, Map meta) { this.pageSource=pageSource; this.extend=extend; this.hint=hint; this.dspName=dspName; this.callPath=callPath; this.realPath=realPath; this.interfacesUDFs=interfacesUDFs; this.meta=meta; } private static void init(PageContext pc,InterfaceImpl icfc) throws PageException { if(!StringUtil.isEmpty(icfc.extend) && (icfc.superInterfaces==null || icfc.superInterfaces.length==0)) { icfc.superInterfaces=loadImplements(ThreadLocalPageContext.get(pc),icfc.getPageSource(),icfc.extend,icfc.interfacesUDFs); } else icfc.superInterfaces=EMPTY; } public static InterfaceImpl[] loadImplements(PageContext pc, PageSource child, String lstExtend, Map interfaceUdfs) throws PageException { List<InterfaceImpl> interfaces=new ArrayList<InterfaceImpl>(); loadImplements(pc,child, lstExtend, interfaces, interfaceUdfs); return interfaces.toArray(new InterfaceImpl[interfaces.size()]); } private static void loadImplements(PageContext pc,PageSource child, String lstExtend,List interfaces, Map interfaceUdfs) throws PageException { Array arr = railo.runtime.type.util.ListUtil.listToArrayRemoveEmpty(lstExtend, ','); Iterator<Object> it = arr.valueIterator(); InterfaceImpl ic; String extend; while(it.hasNext()) { extend=((String) it.next()).trim(); ic=ComponentLoader.loadInterface(pc,child,extend,interfaceUdfs); interfaces.add(ic); ic.setUDFListener(interfaceUdfs); if(!StringUtil.isEmpty(ic.extend)) { loadImplements(pc,ic.getPageSource(),ic.extend,interfaces,interfaceUdfs); } } } private void setUDFListener(Map<Collection.Key,UDF> interfacesUDFs) { this.interfacesUDFs=interfacesUDFs; } /*public boolean instanceOf(String type) { boolean b = _instanceOf(type); print.out("instanceOf("+type+"):"+page+":"+b); return b; }*/ public boolean instanceOf(String type) { if(realPath) { if(type.equalsIgnoreCase(callPath)) return true; if(type.equalsIgnoreCase(pageSource.getComponentName())) return true; if(type.equalsIgnoreCase(_getName())) return true; } else { if(type.equalsIgnoreCase(callPath)) return true; if(type.equalsIgnoreCase(_getName())) return true; } if(superInterfaces==null){ try { init(null,this); } catch (PageException e) { superInterfaces=EMPTY; } } for(int i=0;i<superInterfaces.length;i++){ if(superInterfaces[i].instanceOf(type))return true; } return false; } /** * @return the callPath */ public String getCallPath() { return callPath; } private String _getName() { // MUST nicht so toll if(callPath==null) return ""; return railo.runtime.type.util.ListUtil.last(callPath,"./",true); } public void registerUDF(String key, UDF udf) { udfs.put(KeyImpl.init(key),udf); interfacesUDFs.put(KeyImpl.init(key), udf); } public void registerUDF(Collection.Key key, UDF udf) { udfs.put(key,udf); interfacesUDFs.put(key, udf); } public void registerUDF(String key, UDFProperties props) { registerUDF(key, new UDFImpl(props)); } public void registerUDF(Collection.Key key, UDFProperties props) { registerUDF(key, new UDFImpl(props)); } @Override public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { DumpTable table = new DumpTable("interface","#99cc99","#ffffff","#000000"); table.setTitle("Interface "+callPath+""+(" "+StringUtil.escapeHTML(dspName))); table.setComment("Interface can not directly invoked as a object"); //if(top.properties.extend.length()>0)table.appendRow(1,new SimpleDumpData("Extends"),new SimpleDumpData(top.properties.extend)); //if(top.properties.hint.trim().length()>0)table.appendRow(1,new SimpleDumpData("Hint"),new SimpleDumpData(top.properties.hint)); //table.appendRow(1,new SimpleDumpData(""),_toDumpData(top,pageContext,maxlevel,access)); return table; } /* * * @return the page * / public InterfacePage getPage() { return page; }*/ public PageSource getPageSource() { return pageSource; } public InterfaceImpl[] getExtends() { return superInterfaces; } public Struct getMetaData(PageContext pc) throws PageException { return _getMetaData(pc,this,false); } public Struct getMetaData(PageContext pc, boolean ignoreCache) throws PageException { return _getMetaData(pc,this,ignoreCache); } private static Struct _getMetaData(PageContext pc,InterfaceImpl icfc, boolean ignoreCache) throws PageException { Page page=MetadataUtil.getPageWhenMetaDataStillValid(pc, icfc, ignoreCache); if(page!=null && page.metaData!=null && page.metaData.get()!=null) return page.metaData.get(); long creationTime=System.currentTimeMillis(); Struct sct=new StructImpl(); ArrayImpl arr=new ArrayImpl(); { Iterator<UDF> it = icfc.udfs.values().iterator(); while(it.hasNext()) { arr.append(it.next().getMetaData(pc)); } } if(icfc.meta!=null) { Iterator it = icfc.meta.entrySet().iterator(); Map.Entry entry; while(it.hasNext()){ entry=(Entry) it.next(); sct.setEL(KeyImpl.toKey(entry.getKey()), entry.getValue()); } } if(!StringUtil.isEmpty(icfc.hint,true))sct.set(KeyConstants._hint,icfc.hint); if(!StringUtil.isEmpty(icfc.dspName,true))sct.set(KeyConstants._displayname,icfc.dspName); init(pc,icfc); if(!ArrayUtil.isEmpty(icfc.superInterfaces)){ Set<String> _set = railo.runtime.type.util.ListUtil.listToSet(icfc.extend,',',true); Struct ex=new StructImpl(); sct.set(KeyConstants._extends,ex); for(int i=0;i<icfc.superInterfaces.length;i++){ if(!_set.contains(icfc.superInterfaces[i].getCallPath())) continue; ex.setEL(KeyImpl.init(icfc.superInterfaces[i].getCallPath()),_getMetaData(pc,icfc.superInterfaces[i],true)); } } if(arr.size()!=0)sct.set(KeyConstants._functions,arr); PageSource ps = icfc.pageSource; sct.set(KeyConstants._name,ps.getComponentName()); sct.set(KeyConstants._fullname,ps.getComponentName()); sct.set(KeyConstants._path,ps.getDisplayPath()); sct.set(KeyConstants._type,"interface"); page.metaData=new MetaDataSoftReference<Struct>(sct,creationTime); return sct; } }