package railo.commons.io.res.type.cfml;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import railo.commons.io.res.Resource;
import railo.commons.io.res.ResourceProvider;
import railo.commons.io.res.Resources;
import railo.commons.io.res.util.ResourceLockImpl;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.Component;
import railo.runtime.PageContext;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.PageException;
import railo.runtime.exp.PageRuntimeException;
import railo.runtime.op.Caster;
import railo.runtime.type.Array;
public class CFMLResourceProvider implements ResourceProvider {
private static final Object[] ZERO_ARGS = new Object[0];
private int lockTimeout=20000;
private final ResourceLockImpl lock=new ResourceLockImpl(lockTimeout,false);
private String scheme;
private Map args;
//private ResourceProvider provider;
private Resources resources;
private String cfcPath;
private Component component;
private boolean useStreams=false;
@Override
public ResourceProvider init(String scheme, Map args) {
this.scheme=scheme;
this.args=args;
// CFC Path
cfcPath=Caster.toString(args.get("cfc"),null);
if(StringUtil.isEmpty(cfcPath,true))
cfcPath=Caster.toString(args.get("component"),null);
// use Streams for data
Boolean _useStreams = Caster.toBoolean(args.get("use-streams"),null);
if(_useStreams==null)_useStreams = Caster.toBoolean(args.get("usestreams"),null);
if(_useStreams!=null)useStreams=_useStreams.booleanValue();
return this;
}
@Override
public Resource getResource(String path) {
path=ResourceUtil.removeScheme(scheme,path);
path=ResourceUtil.prettifyPath(path);
if(!StringUtil.startsWith(path,'/'))path="/"+path;
return callResourceRTE(null, null, "getResource", new Object[]{path},false);
}
@Override
public String getScheme() {
return scheme;
}
@Override
public Map getArguments() {
return args;
}
@Override
public void setResources(Resources resources) {
this.resources=resources;
}
@Override
public boolean isCaseSensitive() {
return callbooleanRTE(null,null, "isCaseSensitive", ZERO_ARGS);
}
@Override
public boolean isModeSupported() {
return callbooleanRTE(null,null, "isModeSupported", ZERO_ARGS);
}
@Override
public boolean isAttributesSupported() {
return callbooleanRTE(null,null, "isAttributesSupported", ZERO_ARGS);
}
public int getLockTimeout() {
return lockTimeout;
}
@Override
public void lock(Resource res) throws IOException {
lock.lock(res);
}
@Override
public void unlock(Resource res) {
lock.unlock(res);
}
@Override
public void read(Resource res) throws IOException {
lock.read(res);
}
public boolean isUseStreams() {
return useStreams;
}
Resource callResourceRTE(PageContext pc,Component cfc,String methodName, Object[] args, boolean allowNull) {
pc = ThreadLocalPageContext.get(pc);
try {
Object res = call(pc,getCFC(pc,cfc), methodName, args);
if(allowNull && res==null) return null;
return new CFMLResource(this,Caster.toComponent(res));
}
catch (PageException pe) {pe.printStackTrace();
throw new PageRuntimeException(pe);
}
}
Resource[] callResourceArrayRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
pc = ThreadLocalPageContext.get(pc);
try {
Array arr = Caster.toArray(call(pc,getCFC(pc,cfc), methodName, args));
Iterator<Object> it = arr.valueIterator();
CFMLResource[] resources=new CFMLResource[arr.size()];
int index=0;
while(it.hasNext()){
resources[index++]=new CFMLResource(this,Caster.toComponent(it.next()));
}
return resources;
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
int callintRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
try {
return callint(pc,cfc, methodName, args);
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
int callint(PageContext pc,Component cfc,String methodName, Object[] args) throws PageException {
return Caster.toIntValue(call(pc,cfc,methodName, args));
}
long calllongRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
try {
return calllong(pc,cfc, methodName, args);
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
long calllong(PageContext pc,Component cfc,String methodName, Object[] args) throws PageException {
return Caster.toLongValue(call(pc,cfc,methodName, args));
}
boolean callbooleanRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
try {
return callboolean(pc,cfc, methodName, args);
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
boolean callboolean(PageContext pc,Component cfc,String methodName, Object[] args) throws PageException {
return Caster.toBooleanValue(call(pc,cfc,methodName, args));
}
String callStringRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
try {
return Caster.toString(call(pc,cfc,methodName, args));
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
String callString(PageContext pc,Component cfc,String methodName, Object[] args) throws PageException {
return Caster.toString(call(pc,cfc,methodName, args));
}
Object callRTE(PageContext pc,Component cfc,String methodName, Object[] args) {
try {
return call(pc,cfc,methodName, args);
}
catch (PageException pe) {
throw new PageRuntimeException(pe);
}
}
Object call(PageContext pc,Component cfc,String methodName, Object[] args) throws PageException {
pc = ThreadLocalPageContext.get(pc);
return getCFC(pc, cfc).call(pc, methodName, args);
}
private Component getCFC(PageContext pc,Component cfc) throws PageException {
if(cfc!=null) return cfc;
if(component!=null) return component;
if(StringUtil.isEmpty(cfcPath,true))throw new ApplicationException("you need to define the argument [component] for the [CFMLResourceProvider]");
cfcPath=cfcPath.trim();
component=pc.loadComponent(cfcPath);
call(pc, component, "init", new Object[]{scheme,Caster.toStruct(args)});
return component;
}
}