Last active
March 29, 2016 10:58
-
-
Save andreybpanfilov/ce07b4b1eef6c1885163 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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