001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime; 020 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.Iterator; 024import java.util.List; 025import java.util.Map; 026import java.util.Map.Entry; 027import java.util.Set; 028 029import lucee.commons.lang.StringUtil; 030import lucee.runtime.component.ComponentLoader; 031import lucee.runtime.component.MetaDataSoftReference; 032import lucee.runtime.component.MetadataUtil; 033import lucee.runtime.dump.DumpData; 034import lucee.runtime.dump.DumpProperties; 035import lucee.runtime.dump.DumpTable; 036import lucee.runtime.engine.ThreadLocalPageContext; 037import lucee.runtime.exp.PageException; 038import lucee.runtime.type.Array; 039import lucee.runtime.type.ArrayImpl; 040import lucee.runtime.type.Collection; 041import lucee.runtime.type.KeyImpl; 042import lucee.runtime.type.Struct; 043import lucee.runtime.type.StructImpl; 044import lucee.runtime.type.UDF; 045import lucee.runtime.type.UDFImpl; 046import lucee.runtime.type.UDFProperties; 047import lucee.runtime.type.util.ArrayUtil; 048import lucee.runtime.type.util.KeyConstants; 049 050/** 051 * 052 * MUST add handling for new attributes (style, namespace, serviceportname, porttypename, wsdlfile, bindingname, and output) 053 */ 054public class InterfaceImpl implements Interface { 055 056 private static final long serialVersionUID = -2488865504508636253L; 057 058 private static final InterfaceImpl[] EMPTY = new InterfaceImpl[]{}; 059 060 //private InterfacePage page; 061 private PageSource pageSource; 062 private String extend; 063 private String hint; 064 private String dspName; 065 private String callPath; 066 private boolean relPath; 067 private Map meta; 068 069 private InterfaceImpl[] superInterfaces; 070 071 private Map<Collection.Key,UDF> udfs=new HashMap<Collection.Key,UDF>(); 072 private Map<Collection.Key,UDF> interfacesUDFs; 073 074 /** 075 * Constructor of the Component 076 * @param output 077 * @param extend 078 * @param hint 079 * @param dspName 080 */ 081 public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean relPath,Map interfacesUDFs) { 082 this(page.getPageSource(),extend, hint, dspName,callPath, relPath,interfacesUDFs,null); 083 } 084 public InterfaceImpl(InterfacePage page,String extend, String hint, String dspName,String callPath, boolean relPath,Map interfacesUDFs, Map meta) { 085 this(page.getPageSource(),extend, hint, dspName,callPath, relPath,interfacesUDFs,meta); 086 } 087 public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean relPath,Map interfacesUDFs) { 088 this(pageSource, extend, hint, dspName, callPath, relPath, interfacesUDFs, null); 089 } 090 public InterfaceImpl(PageSource pageSource,String extend, String hint, String dspName,String callPath, boolean relPath,Map interfacesUDFs, Map meta) { 091 this.pageSource=pageSource; 092 this.extend=extend; 093 this.hint=hint; 094 this.dspName=dspName; 095 this.callPath=callPath; 096 this.relPath=relPath; 097 this.interfacesUDFs=interfacesUDFs; 098 this.meta=meta; 099} 100 101 102 103 104 105 private static void init(PageContext pc,InterfaceImpl icfc) throws PageException { 106 if(!StringUtil.isEmpty(icfc.extend) && (icfc.superInterfaces==null || icfc.superInterfaces.length==0)) { 107 icfc.superInterfaces=loadImplements(ThreadLocalPageContext.get(pc),icfc.getPageSource(),icfc.extend,icfc.interfacesUDFs); 108 } 109 else icfc.superInterfaces=EMPTY; 110 } 111 112 113 public static InterfaceImpl[] loadImplements(PageContext pc, PageSource child, String lstExtend, Map interfaceUdfs) throws PageException { 114 List<InterfaceImpl> interfaces=new ArrayList<InterfaceImpl>(); 115 loadImplements(pc,child, lstExtend, interfaces, interfaceUdfs); 116 return interfaces.toArray(new InterfaceImpl[interfaces.size()]); 117 118 } 119 120 private static void loadImplements(PageContext pc,PageSource child, String lstExtend,List interfaces, Map interfaceUdfs) throws PageException { 121 122 Array arr = lucee.runtime.type.util.ListUtil.listToArrayRemoveEmpty(lstExtend, ','); 123 Iterator<Object> it = arr.valueIterator(); 124 InterfaceImpl ic; 125 String extend; 126 127 while(it.hasNext()) { 128 extend=((String) it.next()).trim(); 129 ic=ComponentLoader.loadInterface(pc,child,extend,interfaceUdfs); 130 interfaces.add(ic); 131 ic.setUDFListener(interfaceUdfs); 132 if(!StringUtil.isEmpty(ic.extend)) { 133 loadImplements(pc,ic.getPageSource(),ic.extend,interfaces,interfaceUdfs); 134 } 135 } 136 } 137 138 private void setUDFListener(Map<Collection.Key,UDF> interfacesUDFs) { 139 this.interfacesUDFs=interfacesUDFs; 140 } 141 142 143 144 /*public boolean instanceOf(String type) { 145 boolean b = _instanceOf(type); 146 print.out("instanceOf("+type+"):"+page+":"+b); 147 return b; 148 }*/ 149 public boolean instanceOf(String type) { 150 if(relPath) { 151 if(type.equalsIgnoreCase(callPath)) return true; 152 if(type.equalsIgnoreCase(pageSource.getComponentName())) return true; 153 if(type.equalsIgnoreCase(_getName())) return true; 154 } 155 else { 156 if(type.equalsIgnoreCase(callPath)) return true; 157 if(type.equalsIgnoreCase(_getName())) return true; 158 } 159 if(superInterfaces==null){ 160 try { 161 init(null,this); 162 } catch (PageException e) { 163 superInterfaces=EMPTY; 164 } 165 } 166 for(int i=0;i<superInterfaces.length;i++){ 167 if(superInterfaces[i].instanceOf(type))return true; 168 } 169 return false; 170 } 171 172 173 /** 174 * @return the callPath 175 */ 176 public String getCallPath() { 177 return callPath; 178 } 179 180 181 182 private String _getName() { // MUST nicht so toll 183 if(callPath==null) return ""; 184 return lucee.runtime.type.util.ListUtil.last(callPath,"./",true); 185 } 186 187 public void registerUDF(String key, UDF udf) { 188 udfs.put(KeyImpl.init(key),udf); 189 interfacesUDFs.put(KeyImpl.init(key), udf); 190 } 191 192 public void registerUDF(Collection.Key key, UDF udf) { 193 udfs.put(key,udf); 194 interfacesUDFs.put(key, udf); 195 } 196 197 public void registerUDF(String key, UDFProperties props) { 198 registerUDF(key, new UDFImpl(props)); 199 } 200 201 public void registerUDF(Collection.Key key, UDFProperties props) { 202 registerUDF(key, new UDFImpl(props)); 203 } 204 205 206 207 208 209 210 211 212 @Override 213 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 214 DumpTable table = new DumpTable("interface","#99cc99","#ffffff","#000000"); 215 table.setTitle("Interface "+callPath+""+(" "+StringUtil.escapeHTML(dspName))); 216 table.setComment("Interface can not directly invoked as a object"); 217 //if(top.properties.extend.length()>0)table.appendRow(1,new SimpleDumpData("Extends"),new SimpleDumpData(top.properties.extend)); 218 //if(top.properties.hint.trim().length()>0)table.appendRow(1,new SimpleDumpData("Hint"),new SimpleDumpData(top.properties.hint)); 219 220 //table.appendRow(1,new SimpleDumpData(""),_toDumpData(top,pageContext,maxlevel,access)); 221 return table; 222 } 223 224 /* * 225 * @return the page 226 * / 227 public InterfacePage getPage() { 228 return page; 229 }*/ 230 231 public PageSource getPageSource() { 232 return pageSource; 233 } 234 public InterfaceImpl[] getExtends() { 235 return superInterfaces; 236 } 237 238 239 public Struct getMetaData(PageContext pc) throws PageException { 240 return _getMetaData(pc,this,false); 241 } 242 public Struct getMetaData(PageContext pc, boolean ignoreCache) throws PageException { 243 return _getMetaData(pc,this,ignoreCache); 244 } 245 private static Struct _getMetaData(PageContext pc,InterfaceImpl icfc, boolean ignoreCache) throws PageException { 246 Page page=MetadataUtil.getPageWhenMetaDataStillValid(pc, icfc, ignoreCache); 247 if(page!=null && page.metaData!=null && page.metaData.get()!=null) return page.metaData.get(); 248 249 long creationTime=System.currentTimeMillis(); 250 251 252 Struct sct=new StructImpl(); 253 ArrayImpl arr=new ArrayImpl(); 254 { 255 Iterator<UDF> it = icfc.udfs.values().iterator(); 256 while(it.hasNext()) { 257 arr.append(it.next().getMetaData(pc)); 258 } 259 } 260 261 if(icfc.meta!=null) { 262 Iterator it = icfc.meta.entrySet().iterator(); 263 Map.Entry entry; 264 while(it.hasNext()){ 265 entry=(Entry) it.next(); 266 sct.setEL(KeyImpl.toKey(entry.getKey()), entry.getValue()); 267 } 268 } 269 270 271 if(!StringUtil.isEmpty(icfc.hint,true))sct.set(KeyConstants._hint,icfc.hint); 272 if(!StringUtil.isEmpty(icfc.dspName,true))sct.set(KeyConstants._displayname,icfc.dspName); 273 init(pc,icfc); 274 if(!ArrayUtil.isEmpty(icfc.superInterfaces)){ 275 Set<String> _set = lucee.runtime.type.util.ListUtil.listToSet(icfc.extend,',',true); 276 Struct ex=new StructImpl(); 277 sct.set(KeyConstants._extends,ex); 278 for(int i=0;i<icfc.superInterfaces.length;i++){ 279 if(!_set.contains(icfc.superInterfaces[i].getCallPath())) continue; 280 ex.setEL(KeyImpl.init(icfc.superInterfaces[i].getCallPath()),_getMetaData(pc,icfc.superInterfaces[i],true)); 281 } 282 283 } 284 285 if(arr.size()!=0)sct.set(KeyConstants._functions,arr); 286 PageSource ps = icfc.pageSource; 287 sct.set(KeyConstants._name,ps.getComponentName()); 288 sct.set(KeyConstants._fullname,ps.getComponentName()); 289 290 sct.set(KeyConstants._path,ps.getDisplayPath()); 291 sct.set(KeyConstants._type,"interface"); 292 293 294 page.metaData=new MetaDataSoftReference<Struct>(sct,creationTime); 295 return sct; 296 } 297 298}