/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package Sirius.navigator.connection; import Sirius.navigator.exception.ConnectionException; import Sirius.navigator.exception.SqlConnectionException; import Sirius.server.localserver.attribute.ClassAttribute; import Sirius.server.localserver.method.MethodMap; import Sirius.server.middleware.interfaces.proxy.MetaService; import Sirius.server.middleware.types.AbstractAttributeRepresentationFormater; import Sirius.server.middleware.types.HistoryObject; import Sirius.server.middleware.types.LightweightMetaObject; import Sirius.server.middleware.types.Link; import Sirius.server.middleware.types.MetaClass; import Sirius.server.middleware.types.MetaObject; import Sirius.server.middleware.types.Node; import Sirius.server.newuser.User; import Sirius.server.newuser.UserException; import Sirius.server.newuser.UserGroup; import Sirius.server.search.SearchOption; import Sirius.server.search.SearchResult; import Sirius.server.search.store.Info; import Sirius.server.search.store.QueryData; import Sirius.util.image.ImageHashMap; import org.apache.log4j.Logger; import java.awt.GraphicsEnvironment; import java.io.File; import java.rmi.RemoteException; import java.sql.SQLException; import java.util.Collection; import java.util.HashMap; import java.util.Vector; import javax.swing.Icon; import de.cismet.cids.navigator.utils.ClassCacheMultiple; import de.cismet.cids.server.CallServerService; import de.cismet.cids.server.actions.ServerActionParameter; import de.cismet.cids.server.search.CidsServerSearch; import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; import de.cismet.netutil.Proxy; import de.cismet.reconnector.Reconnector; /** * DOCUMENT ME! * * @author martin.scholl@cismet.de * @version $Revision$, $Date$ */ public class RESTfulConnection implements Connection, Reconnectable<CallServerService> { //~ Static fields/initializers --------------------------------------------- protected static final transient Logger LOG = Logger.getLogger(RESTfulConnection.class); private static final String DISABLE_MO_FILENAME = "cids_disable_lwmo"; // NOI18N //~ Instance fields -------------------------------------------------------- protected Reconnector<CallServerService> reconnector; protected transient CallServerService connector; private final transient boolean isLWMOEnabled; //~ Constructors ----------------------------------------------------------- /** * Creates a new RESTfulConnection object. */ public RESTfulConnection() { final String uHome = System.getProperty("user.home"); // NOI18N if (uHome != null) { final File homeDir = new File(uHome); final File disableIndicator = new File(homeDir, DISABLE_MO_FILENAME); isLWMOEnabled = !disableIndicator.isFile(); if (!isLWMOEnabled) { LOG.warn("LIGHTWIGHTMETAOBJECT CODE IS DISABLED! FOUND FILE: " + disableIndicator); // NOI18N } } else { isLWMOEnabled = true; } } //~ Methods ---------------------------------------------------------------- @Override public Reconnector<CallServerService> getReconnector() { return reconnector; } @Override public boolean connect(final String callserverURL) throws ConnectionException { return connect(callserverURL, null); } /** * DOCUMENT ME! * * @param callserverURL DOCUMENT ME! * @param proxy DOCUMENT ME! * * @return DOCUMENT ME! */ protected Reconnector<CallServerService> createReconnector(final String callserverURL, final Proxy proxy) { reconnector = new RESTfulReconnector(CallServerService.class, callserverURL, proxy); reconnector.useDialog(!GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance(), null); return reconnector; } @Override public boolean connect(final String callserverURL, final Proxy proxy) throws ConnectionException { connector = createReconnector(callserverURL, proxy).getProxy(); try { connector.getDomains(); } catch (final Exception e) { final String message = "no connection to restful interface"; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } return true; } @Override public boolean reconnect() throws ConnectionException { if (LOG.isInfoEnabled()) { LOG.info("reconnect not necessary for RESTful connector"); // NOI18N } return true; } @Override public void disconnect() { connector = null; } @Override public boolean isConnected() { return connector != null; } @Override public String[] getDomains() throws ConnectionException { try { return connector.getDomains(); } catch (final Exception e) { final String message = "cannot get domains"; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public ImageHashMap getDefaultIcons() throws ConnectionException { try { return new ImageHashMap(connector.getDefaultIcons()); } catch (final Exception e) { final String message = "cannot get default icons"; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Icon getDefaultIcon(final String name) throws ConnectionException { try { return getDefaultIcons().get(name); } catch (final Exception e) { final String message = "cannot get default icon with name: " + name; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public User getUser(final String userGroupLsName, final String userGroupName, final String userLsName, final String userName, final String password) throws ConnectionException, UserException { try { return connector.getUser(userGroupLsName, userGroupName, userLsName, userName, password); } catch (final UserException e) { final String message = "cannot get user: " // NOI18N + userGroupLsName + " :: " // NOI18N + userGroupName + " :: " // NOI18N + userLsName + " :: " // NOI18N + userName + " :: ****"; LOG.error(message, e); throw e; } catch (final Exception e) { final String message = "cannot get user: " // NOI18N + userGroupLsName + " :: " // NOI18N + userGroupName + " :: " // NOI18N + userLsName + " :: " // NOI18N + userName + " :: ****"; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Vector getUserGroupNames() throws ConnectionException { try { return connector.getUserGroupNames(); } catch (final Exception e) { final String message = "could not get usergroup names"; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Vector getUserGroupNames(final String username, final String domain) throws ConnectionException, UserException { try { return connector.getUserGroupNames(username, domain); } catch (final Exception e) { final String message = "could not get usergroup names by username,domain: " + username + "@" + domain; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public boolean changePassword(final User user, final String oldPassword, final String newPassword) throws ConnectionException, UserException { try { return connector.changePassword(user, oldPassword, newPassword); } catch (final Exception e) { final String message = "could not change password: " + user + " :: " + oldPassword + " :: " + newPassword; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node[] getRoots(final User user) throws ConnectionException { try { return connector.getRoots(user); } catch (final Exception e) { final String message = "could not get roots for user: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node[] getRoots(final User user, final String domain) throws ConnectionException { try { return connector.getRoots(user, domain); } catch (final Exception e) { final String message = "could not get roots for user: " + user + "@" + domain; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node[] getChildren(final Node node, final User user) throws ConnectionException { try { return connector.getChildren(node, user); } catch (final Exception e) { final String message = "could not get children for node and user: " + node + " :: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node getNode(final User user, final int nodeID, final String domain) throws ConnectionException { try { return connector.getMetaObjectNode(user, nodeID, domain); } catch (final Exception e) { final String message = "could not get node for user, nodeID, domain: " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + nodeID; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node addNode(final Node node, final Link parent, final User user) throws ConnectionException { try { return connector.addNode(node, parent, user); } catch (final Exception e) { final String message = "could not add node with parent and user: " + node + " :: " + parent + " :: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public boolean deleteNode(final Node node, final User user) throws ConnectionException { try { return connector.deleteNode(node, user); } catch (final Exception e) { final String message = "could not delete node for user: " + node + " :: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public boolean addLink(final Node from, final Node to, final User user) throws ConnectionException { try { return connector.addLink(from, to, user); } catch (final Exception e) { final String message = "could not add link, node from, to, user: " + from + " :: " + to + ":: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public boolean deleteLink(final Node from, final Node to, final User user) throws ConnectionException { try { return connector.deleteLink(from, to, user); } catch (final Exception e) { final String message = "could not delete link, node from, to, user: " + from + " :: " + to + ":: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Node[] getClassTreeNodes(final User user) throws ConnectionException { try { return connector.getClassTreeNodes(user); } catch (final Exception e) { final String message = "could not get classtree nodes for user: " + user; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaClass getMetaClass(final User user, final int classID, final String domain) throws ConnectionException { try { return connector.getClass(user, classID, domain); } catch (final Exception e) { final String message = "could not get metaclass for user, domain, classid " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + classID; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaClass[] getClasses(final User user, final String domain) throws ConnectionException { try { return connector.getClasses(user, domain); } catch (final Exception e) { final String message = "could not get classes for user, doamin: " + user + "@" + domain; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject getMetaObject(final User user, final int objectID, final int classID, final String domain) throws ConnectionException { try { return connector.getMetaObject(user, objectID, classID, domain); } catch (final Exception e) { final String message = "could not get metaobject for user, objectid, classid, domain: " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + objectID + " :: " // NOI18N + classID; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getMetaObjectByQuery(final User user, final String query) throws ConnectionException { try { return connector.getMetaObject(user, query); } catch (final Exception e) { final String message = "could not get metaobject for user, query: " + user + " :: " + query; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getMetaObjectByQuery(final User user, final String query, final String domain) throws ConnectionException { try { return connector.getMetaObject(user, query, domain); } catch (final Exception e) { final String message = "could not get metaobject for user, query, domain: " + user + " :: " // NOI18N + query + " :: " // NOI18N + domain; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject insertMetaObject(final User user, final MetaObject metaObject, final String domain) throws ConnectionException { try { return connector.insertMetaObject(user, metaObject, domain); } catch (final Exception e) { final String message = "could not insert metaobject for user, metaobject, domain: " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + metaObject; LOG.error(message, e); /* *if the top level cause was an SQL Exception, we throw an instance of SqlConnectionException which are * visualised with a custom error dialog by the MethodManager */ final Throwable initialCause = getTopInitialCause(e); if (initialCause instanceof SQLException) { throw new SqlConnectionException(initialCause.getMessage(), initialCause); } else { throw new ConnectionException(message, e); } } } @Override public int updateMetaObject(final User user, final MetaObject metaObject, final String domain) throws ConnectionException { try { return connector.updateMetaObject(user, metaObject, domain); } catch (final Exception e) { final String message = "could not update metaobject for user, metaobject, domain: " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + metaObject; LOG.error(message, e); /* *if the top level cause was an SQL Exception, we throw an instance of SqlConnectionException which are * visualised with a custom error dialog by the MethodManager */ final Throwable initialCause = getTopInitialCause(e); if (initialCause instanceof SQLException) { throw new SqlConnectionException(initialCause.getMessage(), initialCause); } else { throw new ConnectionException(message, e); } } } @Override public int deleteMetaObject(final User user, final MetaObject metaObject, final String domain) throws ConnectionException { try { return connector.deleteMetaObject(user, metaObject, domain); } catch (final Exception e) { final String message = "could not delete metaobject for user, metaobject, domain: " // NOI18N + user + "@" // NOI18N + domain + " :: " // NOI18N + metaObject; LOG.error(message, e); /* *if the top level cause was an SQL Exception, we throw an instance of SqlConnectionException which are * visualised with a custom error dialog by the MethodManager */ final Throwable initialCause = getTopInitialCause(e); if (initialCause instanceof SQLException) { throw new SqlConnectionException(initialCause.getMessage(), initialCause); } else { throw new ConnectionException(message, e); } } } @Override public MetaObject getInstance(final User user, final MetaClass c) throws ConnectionException { try { return connector.getInstance(user, c); } catch (final Exception e) { final String message = "could not get instance for user, metaclass: " + user + " :: " + c; // NOI18N LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getAllLightweightMetaObjectsForClass(final int classId, final User user, final String[] representationFields, final String representationPattern) throws ConnectionException { try { if (isLWMOEnabled) { final LightweightMetaObject[] lwmos = connector.getAllLightweightMetaObjectsForClass( classId, user, representationFields, representationPattern); return initLWMOs(lwmos, null); } else { return getLWMOFallback(classId, user); } } catch (final Exception e) { final String message = "could not get all lightweight MOs for classid, user, fields, pattern: " // NOI18N + classId + " :: " // NOI18N + user + " :: " // NOI18N + representationFields + " :: " // NOI18N + representationPattern; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getAllLightweightMetaObjectsForClass(final int classId, final User user, final String[] representationFields, final AbstractAttributeRepresentationFormater formater) throws ConnectionException { try { if (isLWMOEnabled) { final LightweightMetaObject[] lwmo = connector.getAllLightweightMetaObjectsForClass( classId, user, representationFields); return initLWMOs(lwmo, formater); } else { return getLWMOFallback(classId, user); } } catch (final Exception e) { final String message = "could not get all lightweight MOs for classid, user, fields: " // NOI18N + classId + " :: " // NOI18N + user + " :: " // NOI18N + representationFields; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getLightweightMetaObjectsByQuery(final int classId, final User user, final String query, final String[] representationFields, final String representationPattern) throws ConnectionException { try { if (isLWMOEnabled) { final LightweightMetaObject[] lwmo = connector.getLightweightMetaObjectsByQuery( classId, user, query, representationFields, representationPattern); return initLWMOs(lwmo, null); } else { return getLWMOFallback(classId, user); } } catch (final Exception e) { final String message = "could not get all lightweight MOs for classid, user, fields, pattern: " // NOI18N + classId + " :: " // NOI18N + user + " :: " // NOI18N + representationFields + " :: " // NOI18N + representationPattern; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public MetaObject[] getLightweightMetaObjectsByQuery(final int classId, final User user, final String query, final String[] representationFields, final AbstractAttributeRepresentationFormater formater) throws ConnectionException { try { if (isLWMOEnabled) { final LightweightMetaObject[] lwmo = connector.getLightweightMetaObjectsByQuery( classId, user, query, representationFields); return initLWMOs(lwmo, formater); } else { return getLWMOFallback(classId, user); } } catch (final Exception e) { final String message = "could not get all lightweight MOs for classid, user, fields: " // NOI18N + classId + " :: " // NOI18N + user + " :: " // NOI18N + representationFields; LOG.error(message, e); throw new ConnectionException(message, e); } } @Override public Collection customServerSearch(final User user, final CidsServerSearch serverSearch) throws ConnectionException { try { return connector.customServerSearch(user, serverSearch); } catch (final Exception e) { final String message = "error during custom search"; throw new ConnectionException(message, e); } } /** * DOCUMENT ME! * * @param e DOCUMENT ME! * * @return DOCUMENT ME! */ private Throwable getTopInitialCause(final Exception e) { Throwable initialCause = e.getCause(); while (initialCause.getCause() != null) { initialCause = initialCause.getCause(); } return initialCause; } /** * Initializes LWMOs with the appropriate metaservice and string formatter. * * @param lwmos DOCUMENT ME! * @param formater DOCUMENT ME! * * @return DOCUMENT ME! */ private MetaObject[] initLWMOs(final LightweightMetaObject[] lwmos, final AbstractAttributeRepresentationFormater formater) { if (lwmos != null) { final MetaService msServer = (MetaService)connector; for (final LightweightMetaObject lwmo : lwmos) { if (lwmo != null) { lwmo.setMetaService(msServer); if (formater != null) { lwmo.setFormater(formater); } } } } return lwmos; } /** * !For debugging purpose only. Do not use! * * @param classId DOCUMENT ME! * @param user DOCUMENT ME! * * @return DOCUMENT ME! * * @throws ConnectionException DOCUMENT ME! */ private MetaObject[] getLWMOFallback(final int classId, final User user) throws ConnectionException { final MetaClass mc = ClassCacheMultiple.getMetaClass(user.getDomain(), classId); final ClassAttribute ca = mc.getClassAttribute("sortingColumn"); // NOI18N final String orderBy; if (ca == null) { orderBy = ""; // NOI18N } else { orderBy = " order by " // NOI18N + ca.getValue().toString(); } final String query = "select " // NOI18N + mc.getID() + "," // NOI18N + mc.getPrimaryKey() + " from " // NOI18N + mc.getTableName() + orderBy; return getMetaObjectByQuery(user, query); } @Override public String getConfigAttr(final User user, final String key) throws ConnectionException { try { return connector.getConfigAttr(user, key); } catch (final RemoteException e) { throw new ConnectionException("could not get config attr for user: " + user, e); // NOI18N } } @Override public boolean hasConfigAttr(final User user, final String key) throws ConnectionException { try { return connector.hasConfigAttr(user, key); } catch (final RemoteException e) { throw new ConnectionException("could not check config attr for user: " + user, e); // NOI18N } } @Override public HistoryObject[] getHistory(final int classId, final int objectId, final String domain, final User user, final int elements) throws ConnectionException { try { return connector.getHistory(classId, objectId, domain, user, elements); } catch (final RemoteException e) { throw new ConnectionException("could not get history: classId: " + classId + " || objectId: " // NOI18N + objectId + " || domain: " + domain + " || user: " + user + " || elements: " + elements, // NOI18N e); } } @Override public Object executeTask(final User user, final String taskname, final String taskdomain, final Object body, final ServerActionParameter... params) throws ConnectionException { try { // FIXME: workaround for legacy clients that do not support GenericResourceWithContentType final Object taskResult = connector.executeTask(user, taskname, taskdomain, body, params); if ((taskResult != null) && GenericResourceWithContentType.class.isAssignableFrom(taskResult.getClass())) { LOG.warn("REST Action '" + taskname + "' completed, GenericResourceWithContentType with type '" + ((GenericResourceWithContentType)taskResult).getContentType() + "' generated."); return ((GenericResourceWithContentType)taskResult).getRes(); } else { return taskResult; } } catch (final RemoteException e) { throw new ConnectionException("could not executeTask: taskname: " + taskname + " || body: " + body + " || taskdomain: " + taskdomain + " || user: " + user, e); } } @Override public CallServerService getCallServerService() { return (CallServerService)connector; } }