import com.documentum.com.DfClientX | |
import com.documentum.dmcl.impl.DmclApi | |
import com.documentum.fc.client.* | |
import com.documentum.fc.common.DfId | |
import com.documentum.fc.common.DfLoginInfo | |
import com.documentum.fc.common.DfPreferences | |
import com.documentum.fc.common.IDfAttr | |
import com.documentum.fc.impl.util.holders.IntHolder | |
import groovy.json.JsonOutput | |
import org.codehaus.groovy.tools.shell.Groovysh | |
import org.codehaus.groovy.tools.shell.IO | |
import org.codehaus.groovy.tools.shell.util.NoExitSecurityManager | |
class DfcHell extends Groovysh { | |
static { | |
bootstrap() | |
} | |
static CLIENT = new DfClientX().localClient | |
static API = DmclApi.instance | |
String pending | |
DfcHell(final Binding binding, final IO io) { | |
super(binding, io) | |
} | |
void displayError(final Throwable cause) { | |
errorHook.call(cause) | |
} | |
void maybeRecordResult(final Object result) { | |
} | |
void maybeRecordError(Throwable cause) { | |
} | |
@Override | |
boolean isExecutable(String line) { | |
if (isApiCommand(line)) { | |
return true | |
} | |
if (pending) { | |
return true | |
} | |
return super.isExecutable(line); | |
} | |
private boolean isApiCommand(String line) { | |
if (line?.startsWith("?,")) { | |
return true; | |
} | |
String command = getCommand(line) | |
if (command) { | |
return getCommandType(command) != -1 | |
} | |
return false; | |
} | |
private String getCommand(String line) { | |
StringTokenizer t = new StringTokenizer(line, ",") | |
if (!t.hasMoreTokens()) { | |
return null | |
} | |
return t.nextToken() | |
} | |
private int getCommandType(String command) { | |
IntHolder code = new IntHolder(); | |
IntHolder type = new IntHolder(); | |
IntHolder session = new IntHolder(); | |
API.desc(command, code, type, session) | |
return type.value | |
} | |
@Override | |
protected Object executeCommand(String line) { | |
if (!pending && !isApiCommand(line)) { | |
return super.executeCommand(line) | |
} | |
def out = new StringWriter(), err = new StringWriter() | |
cmd(line, out.buffer, err.buffer) | |
if (err.buffer.length() > 0) { | |
io.err.println("@|bold,red ${err.buffer}|@") | |
} | |
if (out.buffer.length() == 0) { | |
return null | |
} | |
if (out.buffer.indexOf('\n') == -1) { | |
return out.buffer | |
} | |
io.out.println(out.buffer) | |
return null | |
} | |
static void main(String[] args) { | |
Map bindings = [ | |
"load" : DfcHell.&load, | |
"newSession" : DfcHell.&newSession, | |
"withSession": DfcHell.&withSession, | |
"useSession" : DfcHell.&useSession, | |
"disconnect" : DfcHell.&disconnect | |
] | |
final DfcHell shell = new DfcHell(new Binding(bindings), new IO()) | |
int code | |
addShutdownHook { | |
if (code == null) { | |
println('WARNING: Abnormal JVM shutdown detected') | |
} | |
if (shell.history) { | |
shell.history.flush() | |
} | |
} | |
SecurityManager psm = System.getSecurityManager() | |
System.setSecurityManager(new NoExitSecurityManager()) | |
try { | |
code = shell.run(null) | |
} | |
finally { | |
System.setSecurityManager(psm) | |
} | |
System.exit(code) | |
} | |
void apiCmd(line, out, err) { | |
def data = line | |
if (pending) { | |
line = pending | |
} | |
switch (getCommandType(getCommand(line))) { | |
case 0: | |
out.append(API.get(line)) | |
break | |
case 2: | |
out.append(API.exec(line)) | |
break | |
case 1: | |
if (!pending) { | |
pending = line | |
buffers.updateSelected([pending]) | |
break | |
} | |
pending = null | |
buffers.clearSelected() | |
out.append(API.set(line, data)) | |
break | |
default: | |
err.append("Bad command") | |
} | |
} | |
void collCmd(line, out, err) { | |
def parts = line.split(",") | |
if (parts.length < 3) { | |
return | |
} | |
def session = parts[1] | |
def coll = parts[2] | |
if (!coll.matches("q\\d+")) { | |
def query = line.substring(line.indexOf(",", line.indexOf(",") + 1) + 1) | |
coll = API.get(String.format("query,%s,%s", session, query)) | |
} | |
try { | |
boolean empty = true | |
while (API.exec(String.format("next,%s,%s", session, coll))) { | |
empty = false | |
apiCmd(String.format("dump,%s,%s", session, coll), out, err) | |
} | |
if (empty) { | |
out.append("No data") | |
} | |
} finally { | |
API.exec(String.format("close,%s,%s", session, coll)) | |
} | |
} | |
void cmd(line, out, err) { | |
if (!pending && line.startsWith("?,")) { | |
collCmd(line, out, err) | |
} else { | |
apiCmd(line, out, err) | |
} | |
} | |
static bootstrap() { | |
DfPreferences.metaClass.loadProperties = { Map properties -> | |
delegate.loadProperties(new Properties(properties), false) | |
} | |
DfPreferences.metaClass.leftShift = { Map properties -> | |
delegate.loadProperties(properties) | |
} | |
IDfSession.metaClass.findObject = { String identity -> | |
IDfSession session = delegate as IDfSession | |
if (DfId.DF_NULLID_STR.equals(identity)) { | |
return null | |
} | |
if (DfId.isObjectId(identity)) { | |
return session.getObject(DfId.valueOf(identity)) | |
} | |
if (identity?.startsWith('/')) { | |
return session.getObjectByPath(identity) | |
} | |
return session.getObjectByQualification(identity) | |
} | |
IDfSession.metaClass.getUserOrGroup = { String userName -> | |
IDfSession session = delegate as IDfSession | |
def user = session.getUser(userName) | |
if (user?.isGroup()) { | |
user = session.getGroup(userName) | |
} | |
return user | |
} | |
IDfSession.metaClass.query = { String query, Closure closure -> | |
IDfQuery dfQuery = new DfQuery(query) | |
IDfCollection collection = null | |
try { | |
collection = dfQuery.execute(delegate as IDfSession, IDfQuery.DF_EXEC_QUERY) | |
if (closure) { | |
while (collection.next()) { | |
closure(collection.getTypedObject()) | |
} | |
} | |
} finally { | |
if (collection?.getState() != IDfCollection.DF_CLOSED_STATE) { | |
collection?.close() | |
} | |
} | |
} | |
IDfSession.metaClass.query = { String query -> | |
delegate.query(query, null) | |
} | |
IDfSession.metaClass.select = { String query -> | |
IDfQuery dfQuery = new DfQuery(query) | |
return dfQuery.execute(delegate as IDfSession, IDfQuery.DF_EXEC_QUERY) | |
} | |
IDfSession.metaClass.transaction = { Closure closure -> | |
IDfSession session = delegate as IDfSession | |
boolean txStartsHere = false | |
try { | |
if (!session.isTransactionActive()) { | |
txStartsHere = true | |
session.beginTrans() | |
} | |
closure() | |
if (txStartsHere) { | |
session.commitTrans() | |
txStartsHere = false | |
} | |
} finally { | |
if (txStartsHere && session.isTransactionActive()) { | |
session.abortTrans() | |
} | |
} | |
} | |
IDfTypedObject.metaClass.size = { delegate.attrCount } | |
IDfTypedObject.metaClass.getAt = { int index -> | |
def attrCount = delegate.attrCount | |
if (!(index < attrCount)) { | |
return null | |
} | |
return readAttribute(delegate as IDfTypedObject, delegate.getAttr(index).name as String) | |
} | |
IDfTypedObject.metaClass.propertyMissing = { String name -> | |
readAttribute(delegate as IDfTypedObject, name) | |
} | |
IDfTypedObject.metaClass.getMap = { -> | |
readAttributes(delegate as IDfTypedObject) | |
} | |
IDfTypedObject.metaClass.getMap = { List attributes -> | |
readAttributes(delegate as IDfTypedObject, attributes) | |
} | |
IDfTypedObject.metaClass.getJson = { -> | |
JsonOutput.toJson(delegate.getMap()) | |
} | |
IDfTypedObject.metaClass.getJson = { List attributes -> | |
JsonOutput.toJson(delegate.getMap(attributes)) | |
} | |
IDfTypedObject.metaClass.getObject = { String attrName -> | |
getObject(delegate as IDfTypedObject, attrName) | |
} | |
IDfTypedObject.metaClass.getUserOrGroup = { String attrName -> | |
getUserOrGroup(delegate as IDfTypedObject, attrName) | |
} | |
IDfCollection.metaClass.iterator = { | |
return new IDfCollectionIterator(delegate as IDfCollection) | |
} | |
IDfCollection.metaClass.each = { Closure closure -> | |
IDfCollection collection = delegate as IDfCollection | |
try { | |
while (collection.next()) { | |
closure(collection.getTypedObject()) | |
} | |
} finally { | |
if (collection?.getState() != IDfCollection.DF_CLOSED_STATE) { | |
collection?.close() | |
} | |
} | |
} | |
} | |
static load(Map params) { | |
DfPreferences.getInstance() << params | |
} | |
static newSession(Map<String, String> params) { | |
Map<String, String> properties = new HashMap(params); | |
String docbase = properties.remove("docbase") | |
String user = properties.remove("user") | |
String password = properties.remove("password") | |
if (!params.isEmpty()) { | |
DfPreferences.getInstance().loadProperties(properties) | |
} | |
IDfSessionManager sessionManager = CLIENT.newSessionManager() | |
sessionManager.setIdentity(docbase, new DfLoginInfo(user, password)) | |
return sessionManager.getSession(docbase) | |
} | |
static disconnect(IDfSession session) { | |
if (session) { | |
def manager = session.sessionManager | |
if (manager) { | |
manager.release(session) | |
} | |
} | |
} | |
static void useSession(IDfSession session, Closure closure) { | |
if (session) { | |
closure(session) | |
} | |
} | |
static void useSession(Map<String, String> params = null, Closure closure) { | |
def session = null | |
try { | |
session = newSession(params) | |
useSession(session, closure) | |
} finally { | |
disconnect(session) | |
} | |
} | |
static void withSession(IDfSession session, Closure closure) { | |
if (session) { | |
session.with(closure) | |
} | |
} | |
static void withSession(Map<String, String> params = null, Closure closure) { | |
def session = null | |
try { | |
session = newSession(params) | |
withSession(session, closure) | |
} finally { | |
disconnect(session) | |
} | |
} | |
static getObject(IDfTypedObject object, String attribute) { | |
def session = object.session | |
if (!object.hasAttr(attribute)) { | |
return null | |
} | |
def repeating = object.isAttrRepeating(attribute) | |
def closure = { String val -> | |
if (!DfId.isObjectId(val)) { | |
return null | |
} | |
return session.getObject(DfId.valueOf(val)) | |
} | |
def values = readAttribute(object, attribute, IDfAttr.DM_STRING) | |
if (!repeating) { | |
return closure(values as String) | |
} | |
def result = [] as List | |
values?.each { | |
result << closure(it as String) | |
} | |
return result | |
} | |
static getUserOrGroup(IDfTypedObject object, String attribute) { | |
def session = object.session | |
if (!object.hasAttr(attribute)) { | |
return null | |
} | |
def repeating = object.isAttrRepeating(attribute) | |
def closure = { String val -> | |
if (!val?.trim()) { | |
return null | |
} | |
return session.getUserOrGroup(val) | |
} | |
def values = readAttribute(object, attribute, IDfAttr.DM_STRING) | |
if (!repeating) { | |
return closure(values as String) | |
} | |
def result = [] as List | |
values?.each { | |
result << closure(it as String) | |
} | |
return result | |
} | |
static readAttributes(IDfTypedObject object, List attributes = null) { | |
def result = [:] as Map | |
if (!attributes) { | |
attributes = [] | |
def attrCount = object.attrCount | |
for (i in 0..<attrCount) { | |
attributes << object.getAttr(i).name | |
} | |
} | |
for (attribute in attributes) { | |
result.put(attribute, readAttribute(object, attribute as String)) | |
} | |
return result | |
} | |
static readAttribute(IDfTypedObject object, String attribute, type = null, repeating = null) { | |
if (!object.hasAttr(attribute)) { | |
return null | |
} | |
def valueCount = object.getValueCount(attribute) | |
if (!type) { | |
type = object.getAttrDataType(attribute) | |
} | |
if (repeating == null) { | |
repeating = object.isAttrRepeating(attribute) | |
} | |
def closure = { String attrName, int attrType, Integer index = null -> | |
switch (attrType) { | |
case IDfAttr.DM_BOOLEAN: | |
return index == null ? | |
object.getBoolean(attrName) | |
: object.getRepeatingBoolean(attrName, index) | |
case IDfAttr.DM_DOUBLE: | |
return index == null ? | |
object.getDouble(attrName) | |
: object.getRepeatingDouble(attrName, index) | |
case IDfAttr.DM_ID: | |
return index == null ? | |
object.getId(attrName).id | |
: object.getRepeatingId(attrName, index).id | |
case IDfAttr.DM_INTEGER: | |
return index == null ? | |
object.getInt(attrName) | |
: object.getRepeatingInt(attrName, index) | |
case IDfAttr.DM_STRING: | |
return index == null ? | |
object.getString(attrName) | |
: object.getRepeatingString(attrName, index) | |
case IDfAttr.DM_TIME: | |
return index == null ? | |
object.getTime(attrName).date | |
: object.getRepeatingTime(attrName, index).date | |
default: | |
return null | |
} | |
} | |
if (!repeating) { | |
return closure(attribute, type) | |
} | |
List result = [] | |
for (j in 0..<valueCount) { | |
result << closure(attribute, type, j) | |
} | |
return result | |
} | |
static class IDfCollectionIterator implements Iterator<IDfTypedObject> { | |
private IDfTypedObject _next | |
private IDfTypedObject _current | |
private final IDfCollection _collection | |
IDfCollectionIterator(IDfCollection collection) { | |
_collection = collection | |
} | |
@Override | |
boolean hasNext() { | |
if (_next != null) { | |
return true; | |
} | |
if (_collection.getState() == IDfCollection.DF_CLOSED_STATE) { | |
return false; | |
} | |
if (_collection.next()) { | |
_next = _collection.getTypedObject(); | |
return true; | |
} else { | |
if (_collection.getState() != IDfCollection.DF_CLOSED_STATE) { | |
_collection.close() | |
} | |
return false; | |
} | |
} | |
@Override | |
IDfTypedObject next() { | |
if (hasNext()) { | |
_current = _next; | |
_next = null; | |
} else { | |
_next = null; | |
_current = null; | |
} | |
return getCurrent() | |
} | |
@Override | |
void remove() { | |
//do nothing | |
} | |
private IDfTypedObject getCurrent() { | |
if (_current == null) { | |
switch (_collection.getState()) { | |
case IDfCollection.DF_INITIAL_STATE: | |
case IDfCollection.DF_READY_STATE: | |
throw new IllegalStateException("next() not called yet"); | |
case IDfCollection.DF_CLOSED_STATE: | |
throw new IllegalStateException("collection closed"); | |
case IDfCollection.DF_NO_MORE_ROWS_STATE: | |
throw new IllegalStateException("beyond end of collection"); | |
default: | |
throw new IllegalStateException("Unknown state, state: " | |
+ _collection.getState()); | |
} | |
} | |
return _current; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment