![JAR search and dependency download from the Maven repository](/logo.png)
org.tentackle.persist.wurblet.RemoteIncludes Maven / Gradle / Ivy
/*
* Tentackle - https://tentackle.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.tentackle.persist.wurblet;
import org.wurbelizer.wurbel.HeapStream;
import org.wurbelizer.wurbel.WurbelException;
import org.wurbelizer.wurbel.Wurbler;
import org.tentackle.common.StringHelper;
import org.tentackle.model.Entity;
import org.tentackle.wurblet.ModelWurblet;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Date;
/**
* Handles generated .remote and .impl-code.
*
* Also creates the RMI-java files, if missing.
*
* @author harald
*/
public class RemoteIncludes {
private final Wurbler container; // the executing container
private final Entity entity; // the wurblet's entity
private final String className; // classname of persistence object
private final String packageName; // package of the class
private final String superClassName; // name of the superclass
private final String type; // type name (pdo or operation)
private final boolean isOperation; // true if not a PDO but an Operation
private final String remotePrefixBasename; // basename of remotePrefix
private final HeapStream remoteStream; // stream for remote file
private final HeapStream implStream; // stream for impl file
private String pdoClassName; // classname of the pdo interface
private String pdoPackageName; // package name of the pdo interface
private String rmiDirName; // directory of rmi-classes
private String remotePrefix; // prefix of the remote parent class (usually from ant script)
private boolean importSuperDelegate; // create import for superclass/interface of remote delegate
/**
* Create remote includes.
*
* @param wurblet the wurblet
* @throws WurbelException if failed
*/
public RemoteIncludes(ModelWurblet wurblet) throws WurbelException {
container = wurblet.getContainer();
className = wurblet.getClassName();
entity = wurblet.getEntity();
superClassName = StringHelper.getPlainClassName(wurblet.getSuperClassName());
packageName = wurblet.getPackageName();
remotePrefix = container.getProperty(Wurbler.PROPSPACE_EXTRA, "remoteprefix");
try {
pdoClassName = wurblet.getPdoClassName();
}
catch (WurbelException ex) {
// only needed for initial class file generation below
}
if (remotePrefix == null) {
// if not defined, set the default
pdoPackageName = packageName.replace(".persistence.", ".pdo.").replace(".persist.", ".pdo.");
switch (superClassName) {
case "AbstractPersistentObject":
remotePrefix = "org.tentackle.persist.rmi." + superClassName;
importSuperDelegate = true;
break;
case "AbstractDbObject":
remotePrefix = "org.tentackle.dbms.rmi." + superClassName;
importSuperDelegate = true;
break;
default:
remotePrefix = superClassName;
if (pdoClassName != null && className.startsWith(pdoClassName)) {
// subtract from classname to get the tail, something like "PersistenceImpl" or alike
String tail = className.substring(pdoClassName.length());
if (!tail.isEmpty() && remotePrefix.endsWith(tail)) {
remotePrefix = remotePrefix.substring(0, remotePrefix.length() - tail.length());
}
}
}
}
int ndx = remotePrefix.lastIndexOf('.');
remotePrefixBasename = ndx < 0 ? remotePrefix : remotePrefix.substring(ndx + 1);
isOperation = remotePrefix.endsWith("Operation");
type = isOperation ? "operation" : (pdoClassName != null ? "pdo" : "object");
// find directory for remote delegates
rmiDirName = container.getProperty(Wurbler.PROPSPACE_WURBLET, Wurbler.WURBLET_DIRNAME);
rmiDirName += "/rmi";
// create remote stream and file
String remoteName = (pdoClassName != null ? pdoClassName : className) + "RemoteDelegate";
remoteStream = new HeapStream(container, remoteName + "/methods");
checkFile(remoteName, false);
// create impl stream and file
implStream = new HeapStream(container, remoteName + "Impl/methods");
checkFile(remoteName, true);
}
/**
* Marks the heapfiles as discarded.
* Such files should not be used to generate code because their contents are incomplete
* because of former errors. Wurblets reading this file should throw a {@link org.wurbelizer.wurbel.WurbelDiscardException}.
*/
public void discard() {
implStream.discard();
remoteStream.discard();
}
/**
* Appends text to remote file.
*
* @param text the text to append
*/
public void appendRemote(String text) {
remoteStream.append(text);
}
/**
* Appends text to impl file.
*
* @param text the text to append
*/
public void appendImpl(String text) {
implStream.append(text);
}
/**
* @return get the remote stream
*/
public PrintStream getRemoteStream() {
return remoteStream.getStream();
}
/**
* @return the impl stream
*/
public PrintStream getImplStream() {
return implStream.getStream();
}
/**
* Returns whether entity is abstract.
*
* @return true if abstract, false if concrete or no entity (e.g. operation)
*/
private boolean isAbstract() {
return entity != null && entity.isAbstract();
}
/**
* Check if remote file exists. If not, create it.
*/
private void checkFile(String name, boolean impl) throws WurbelException {
// check directory first
new File(rmiDirName).mkdirs();
String fileName = name + (impl ? "Impl" : "") + ".java";
String pathName = rmiDirName + "/" + fileName;
File file = new File(pathName);
if (!file.exists()) {
if (pdoClassName != null) {
// create it
try (PrintStream s = new PrintStream(file)) { // this is ok unbuffered for one time
s.println(
"/*\n" +
" * " + fileName + " (generated " + new Date() + ")\n" +
" */\n\n" +
"package " + packageName + ".rmi;\n\n" +
"import " + pdoPackageName + "." + pdoClassName + ";\n" +
"import " + packageName + "." + className + ";\n" +
"import java.rmi.RemoteException;\n" +
"import java.util.List;\n" +
"import org.tentackle.common.BMoney;\n" +
"import org.tentackle.common.Binary;\n" +
"import org.tentackle.common.DMoney;\n" +
"import org.tentackle.common.Date;\n" +
"import org.tentackle.common.Time;\n" +
"import org.tentackle.common.Timestamp;\n" +
"import org.tentackle.misc.TrackedList;\n" +
"import org.tentackle.persist.rmi.RemoteResultSetCursor;"
);
s.println("import org.tentackle.pdo.DomainContext;");
if (impl) {
if (importSuperDelegate) {
s.println("import " + remotePrefix + "RemoteDelegateImpl;");
}
s.println("import org.tentackle.dbms.rmi.RemoteDbSessionImpl;\n\n");
s.println("/**");
s.println(" * Remote delegate implementation for {@link " + className + "}.");
if (isAbstract()) {
s.println(" * ");
s.println(" * @param the " + type + " interface");
s.println(" * @param the persistence implementation");
}
s.println(" */");
if (isAbstract()) {
s.println("public class " + name + "Impl, P extends " + className + ">");
s.println(" extends " + remotePrefixBasename + "RemoteDelegateImpl");
s.println(" implements " + name + " {\n");
}
else {
s.println("public class " + name + "Impl");
s.println(" extends " + remotePrefixBasename + "RemoteDelegateImpl<" + pdoClassName + "," + className + ">");
s.println(" implements " + name + " {\n");
}
s.println(" /**");
s.println(" * Creates the remote delegate for {@link " + className + "}.");
s.println(" *");
s.println(" * @param session the RMI session");
s.println(" * @param persistenceClass the persistence implementation class");
s.println(" * @param " + type + "Class the " + type + " interface class");
s.println(" */");
if (isAbstract()) {
s.println(" public " + name + "Impl(RemoteDbSessionImpl session, Class persistenceClass, Class " + type + "Class) {");
}
else {
s.println(" public " + name + "Impl(RemoteDbSessionImpl session, Class<" + className +
"> persistenceClass, Class<" + pdoClassName + "> " + type + "Class) {");
}
s.println(" super(session, persistenceClass, " + type + "Class);");
s.println(" }");
}
else {
if (importSuperDelegate) {
s.println("import " + remotePrefix + "RemoteDelegate;");
}
s.println("\n/**");
s.println(" * Remote delegate for {@link " + className + "}.");
if (isAbstract()) {
s.println(" * ");
s.println(" * @param the " + type + " interface");
s.println(" * @param the persistence implementation");
}
s.println(" */");
if (isAbstract()) {
s.println("public interface " + name + ", P extends " + className + ">");
s.println(" extends " + remotePrefixBasename + "RemoteDelegate {\n");
}
else {
s.println("public interface " + name);
s.println(" extends " + remotePrefixBasename + "RemoteDelegate<" + pdoClassName + "," + className + "> {\n");
}
}
s.println(
"\n" +
" // @wurblet inclrmi Include --missingok .$classname/methods\n" +
"}"
);
}
catch (IOException ex) {
throw new WurbelException("printing to " + pathName + " failed", ex);
}
}
else if (superClassName != null && superClassName.equals("AbstractDbObject")) {
// primitive AbstractDbObjects
try (PrintStream s = new PrintStream(file)) { // this is ok unbuffered for one time
s.println(
"/*\n" +
" * " + fileName + " (generated " + new Date() + ")\n" +
" */\n\n" +
"package " + packageName + ".rmi;\n\n" +
"import " + packageName + "." + className + ";\n" +
"import java.rmi.RemoteException;\n" +
"import java.util.List;\n" +
"import org.tentackle.persist.AbstractDbObject;\n" +
"import org.tentackle.misc.TrackedList;"
);
if (impl) {
if (importSuperDelegate) {
s.println("import " + remotePrefix + "RemoteDelegateImpl;");
}
s.println("import org.tentackle.persist.rmi.RemoteDbSessionImpl;\n");
s.println("/**");
s.println(" * Remote delegate implementation for {@link " + className + "}.");
s.println(" * ");
s.println(" * @param the persistence implementation");
s.println(" */");
s.println("public class " + name + "Impl
");
s.println(" extends " + remotePrefixBasename + "RemoteDelegateImpl
");
s.println(" implements " + name + "
{\n\n");
s.println(" /**");
s.println(" * Creates the remote delegate for {@link " + className + "}.");
s.println(" *");
s.println(" * @param session the RMI session");
s.println(" * @param persistenceClass the persistence implementation class");
s.println(" */");
s.println(" public " + name + "Impl(RemoteDbSessionImpl session, Class
persistenceClass) {");
s.println(" super(session, persistenceClass);");
s.println(" }");
}
else {
if (importSuperDelegate) {
s.println("import " + remotePrefix + "RemoteDelegate;");
}
s.println("\n/**");
s.println(" * Remote delegate for {@link " + className + "}.");
s.println(" * ");
s.println(" * @param
the persistence implementation");
s.println(" */");
s.println("public interface " + name + "
");
s.println(" extends " + remotePrefixBasename + "RemoteDelegate
{\n");
}
s.println(
"\n" +
" // @wurblet inclrmi Include --missingok .$classname/methods\n" +
"}"
);
}
catch (IOException ex) {
throw new WurbelException("printing to " + pathName + " failed", ex);
}
}
else {
container.getLogger().warning(pathName + " cannot be generated because " + type + " class is unknown (missing service annotation?)");
}
}
}
}