Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@andreybpanfilov
Last active March 29, 2016 10:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreybpanfilov/ce07b4b1eef6c1885163 to your computer and use it in GitHub Desktop.
Save andreybpanfilov/ce07b4b1eef6c1885163 to your computer and use it in GitHub Desktop.
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