/*
* Copyright 2012 Jason Miller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jj.script;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.mozilla.javascript.BaseFunction;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import com.google.inject.Injector;
/**
* <p>
* A rhino host object exposed to API modules to allow them to
* get instances from the core injector. For now it'll be wrapped up behind
* a function call, it returns whatever getInstance returns, and that's about
* it.
*
* <p>
* Basic concept is that a ModuleScriptEnvironment that is loaded from the
* AppLocation.Assets location will have this function defined in its scope.
* this allows internal scripts to load whatever they need from the surrounding
* environment - getting rid of the "host object" necessity and allowing
* the API to be written as script where appropriate and with no need to wrap up
* the pieces behind the scenes where java makes more sense.
*
* <p>
* This class is not actually serializable! this may need to be taken into
* account at some point - basically this object cannot be shared since it
* requires the injector to work.
*
* @author jason
*
*/
@Singleton
class InjectFunction extends BaseFunction {
static final String NAME = "inject";
private static final long serialVersionUID = 1L;
private transient final Injector injector;
@Inject
InjectFunction(final Injector injector) {
this.injector = injector;
}
@Override
public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
throw new AssertionError("don't new the " + NAME + " function");
}
@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
assert args.length == 1 && args[0] instanceof CharSequence : NAME + " requires one string argument";
try {
Class<?> desiredClass = Class.forName(String.valueOf(args[0]));
return injector.getInstance(desiredClass);
} catch (Exception e) {
throw new AssertionError(NAME + " failed", e);
}
}
}