package play.modules.cream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.core.TransientRepository;
import org.jcrom.Jcrom;
import org.jcrom.annotations.JcrNode;
import play.Invoker.InvocationContext;
import play.Logger;
import play.Play;
import play.PlayPlugin;
import play.classloading.ApplicationClasses.ApplicationClass;
import play.exceptions.UnexpectedException;
import play.modules.cream.annotations.JcrNoSession;
import play.modules.cream.annotations.JcrSession;
import play.modules.cream.helpers.JcrRepositoryCreationHelper;
import play.modules.cream.helpers.JcrRepositoryHelper;
import play.modules.cream.ocm.JcrMapper;
/**
* Cream: JCR Plugin for Play! Framework
*
*/
public class JcrPlugin extends PlayPlugin {
@Override
public void afterInvocation() {
JCR.closeSession();
}
@Override
public void beforeInvocation() {
InvocationContext current = InvocationContext.current();
if (!current.isAnnotationPresent(JcrNoSession.class)) {
Session currentSession = createCurrentSession(current);
JCR.addSession(currentSession);
}
}
@Override
@SuppressWarnings("unchecked")
public Object bind(String name, Class clazz, java.lang.reflect.Type type, Annotation[] annotations,
Map<String, String[]> params) {
if (Model.class.isAssignableFrom(clazz)) {
String keyName = Model.Manager.factoryFor(clazz).keyName();
String idKey = name + "." + keyName;
if (params.containsKey(idKey) && params.get(idKey).length > 0 && params.get(idKey)[0] != null
&& params.get(idKey)[0].trim().length() > 0) {
String id = params.get(idKey)[0];
try {
Model o = (Model) JcrMapper.loadByUUID(clazz, id);
if (o != null) {
return Model.edit(o, name, params, annotations);
}
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
return Model.create(clazz, name, params, annotations);
}
return super.bind(name, clazz, type, annotations, params);
}
@Override
public Object bind(String name, Object o, Map<String, String[]> params) {
if (o instanceof Model) {
return Model.edit(o, name, params, null);
}
return null;
}
@Override
public void enhance(ApplicationClass applicationClass) throws Exception {
new JcrEnhancer().enhanceThisClass(applicationClass);
}
@Override
public String getStatus() {
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter(sw);
out.println("Jcr Repository:");
out.println("~~~~~~~~~~~~~~");
if (JcrRepositoryHelper.repository == null) {
out.println("(not yet initialized)");
return sw.toString();
}
out.println("name: " + JcrRepositoryHelper.repository.getDescriptor(Repository.REP_NAME_DESC));
out.println("version: " + JcrRepositoryHelper.repository.getDescriptor(Repository.REP_VERSION_DESC));
out.println("default workspace: " + JcrRepositoryHelper.defaultWorkspace);
out.println("\nJcr Mapped Classes:");
out.println("~~~~~~~~~~~~~~~~~~");
for (Class clazz : JcrMapper.jcrom.getMappedClasses()) {
out.println(clazz.getName());
}
return sw.toString();
}
@Override
public void invocationFinally() {
JCR.closeSession();
}
@Override
public Model.Factory modelFactory(Class<? extends play.db.Model> modelClass) {
return (modelClass.isAnnotationPresent(JcrNode.class)) ? new JcrModelLoader(modelClass) : null;
}
@Override
public void onApplicationStart() {
mapJcrEntities();
setUpJcrRepository();
}
@Override
public void onApplicationStop() {
JcrRepositoryHelper.shutdown();
}
@Override
public void onInvocationException(Throwable e) {
JCR.closeSession();
}
private Session createCurrentSession(InvocationContext current) {
Session currentSession;
JcrSession jcrConfig = current.getAnnotation(JcrSession.class);
if (jcrConfig != null && StringUtils.isNotBlank(jcrConfig.workspace())) {
currentSession = JcrRepositoryHelper.openSession(jcrConfig.workspace());
} else {
currentSession = JcrRepositoryHelper.openSession();
}
postEvent(JcrPlugin.class.getSimpleName() + ".JcrSessionCreated", currentSession);
return currentSession;
}
private void mapJcrEntities() {
Jcrom jcrom = new Jcrom();
List<Class> jcrClasses = Play.classloader.getAnnotatedClasses(JcrNode.class);
for (Class jcrClass : jcrClasses) {
Logger.trace("Jcrom mapping of %s", jcrClass.getName());
jcrom.map(jcrClass);
}
JcrMetadata jcrMetadata = JcrMetadata.getInstance();
jcrMetadata.intialize(jcrom);
JcrMapper.jcrom = jcrom;
}
private void setUpJcrRepository() {
Repository repository;
Properties p = Play.configuration;
String username = p.getProperty("cream.jcr.username", "anonymous");
String password = p.getProperty("cream.jcr.password", "");
String workspace = p.getProperty("cream.jcr.workspace", "default");
String repoConfiguration = p.getProperty("cream.jcr.configuration", "/play/modules/cream/repository.xml");
if ("transient".equals(p.getProperty("cream.jcr.mode"))) {
repository = new TransientRepository();
} else {
String url = p.getProperty("cream.jcr.url", "");
repository = JcrRepositoryCreationHelper.createRepository(url, repoConfiguration);
}
JcrRepositoryHelper.repository = repository;
JcrRepositoryHelper.defaultCredentials = new SimpleCredentials(username, password.toCharArray());
JcrRepositoryHelper.defaultWorkspace = workspace;
}
}