diff --git a/src/main/java/Sirius/server/middleware/impls/domainserver/DomainServerImpl.java b/src/main/java/Sirius/server/middleware/impls/domainserver/DomainServerImpl.java index 7bade448..0fd3b3f9 100644 --- a/src/main/java/Sirius/server/middleware/impls/domainserver/DomainServerImpl.java +++ b/src/main/java/Sirius/server/middleware/impls/domainserver/DomainServerImpl.java @@ -38,6 +38,7 @@ import Sirius.server.sql.DBConnectionPool; import Sirius.server.sql.PreparableStatement; +import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.openide.util.Lookup; @@ -72,12 +73,16 @@ import de.cismet.cids.server.actions.ScheduledServerActionManager; import de.cismet.cids.server.actions.ServerAction; import de.cismet.cids.server.actions.ServerActionParameter; +import de.cismet.cids.server.search.CidsServerSearch; import de.cismet.cids.server.search.QueryPostProcessor; import de.cismet.cids.server.ws.rest.RESTfulService; import de.cismet.cids.utils.ClassloadingHelper; import de.cismet.cids.utils.serverresources.ServerResourcesLoader; +import de.cismet.cidsx.server.actions.RestApiCidsServerAction; +import de.cismet.cidsx.server.search.RestApiCidsServerSearch; + /** * DOCUMENT ME! * @@ -177,9 +182,23 @@ public DomainServerImpl(final ServerProperties properties) throws Throwable { ex); } + final Collection restServerActions = Lookup.getDefault() + .lookupAll(RestApiCidsServerAction.class); final Collection serverActions = Lookup.getDefault().lookupAll(ServerAction.class); + + for (final ServerAction restServerAction : restServerActions) { + if (logger.isDebugEnabled()) { + logger.debug("Adding REST API Server Action '" + restServerAction.getTaskName() + "'"); + } + serverActionMap.put(restServerAction.getTaskName(), restServerAction); + } + for (final ServerAction serverAction : serverActions) { - serverActionMap.put(serverAction.getTaskName(), serverAction); + if (!serverActionMap.containsKey(serverAction.getTaskName())) { + logger.warn("Adding LEGACY Server Action '" + serverAction.getTaskName() + + "' -> Change to RestApiCidsServerAction"); + serverActionMap.put(serverAction.getTaskName(), serverAction); + } } MetaClassCache.getInstance().setAllClasses(dbServer.getClasses(), properties.getServerName()); @@ -1149,23 +1168,25 @@ public Object executeTask(final User user, final String taskname, final Object body, final ServerActionParameter... params) throws RemoteException { + logger.info("executing task '" + taskname + "' with " + params.length + + " server action parameters and body object: " + (body != null)); if (hasConfigAttr(user, SERVER_ACTION_PERMISSION_ATTRIBUTE_PREFIX + taskname)) { final ServerAction serverAction = serverActionMap.get(taskname); - if (serverAction instanceof MetaServiceStore) { - ((MetaServiceStore)serverAction).setMetaService(this); - } - if (serverAction instanceof CatalogueServiceStore) { - ((CatalogueServiceStore)serverAction).setCatalogueService(this); - } - if (serverAction instanceof UserServiceStore) { - ((UserServiceStore)serverAction).setUserService(this); - } - if (serverAction instanceof Sirius.server.middleware.interfaces.domainserver.UserStore) { - ((Sirius.server.middleware.interfaces.domainserver.UserStore)serverAction).setUser(user); - } - if (serverAction != null) { + if (serverAction instanceof MetaServiceStore) { + ((MetaServiceStore)serverAction).setMetaService(this); + } + if (serverAction instanceof CatalogueServiceStore) { + ((CatalogueServiceStore)serverAction).setCatalogueService(this); + } + if (serverAction instanceof UserServiceStore) { + ((UserServiceStore)serverAction).setUserService(this); + } + if (serverAction instanceof Sirius.server.middleware.interfaces.domainserver.UserStore) { + ((Sirius.server.middleware.interfaces.domainserver.UserStore)serverAction).setUser(user); + } + if (serverAction instanceof ScheduledServerAction) { if (ScheduledServerActionManager.isScheduledServerActionFeatureSupported( dbServer.getActiveDBConnection())) { @@ -1186,15 +1207,24 @@ public Object executeTask(final User user, "this server instance does not support scheduled server action feature"); // NOI18N } } else { - return serverAction.execute(body, params); + final long start = System.currentTimeMillis(); + final Object result = serverAction.execute(body, params); + if (logger.isDebugEnabled()) { + logger.debug("Server Action '" + taskname + "' successfully executed in " + + (System.currentTimeMillis() - start) + "ms."); + } + return result; } } else { + logger.warn("Server Action '" + taskname + "' not found! Returning null."); return null; } } else { - throw new RemoteException("The user " + user + final String message = "The user " + user + "has no permission to execute this task. (Should have an action attribute like this: " - + SERVER_ACTION_PERMISSION_ATTRIBUTE_PREFIX + taskname); + + SERVER_ACTION_PERMISSION_ATTRIBUTE_PREFIX + taskname; + logger.error(message); + throw new RemoteException(message); } } } diff --git a/src/main/java/Sirius/server/middleware/impls/proxy/ActionServiceImpl.java b/src/main/java/Sirius/server/middleware/impls/proxy/ActionServiceImpl.java index 6373bbc3..acda8746 100644 --- a/src/main/java/Sirius/server/middleware/impls/proxy/ActionServiceImpl.java +++ b/src/main/java/Sirius/server/middleware/impls/proxy/ActionServiceImpl.java @@ -36,7 +36,7 @@ public class ActionServiceImpl implements ActionService { //~ Instance fields -------------------------------------------------------- - private Map activeLocalServers; + private final Map activeLocalServers; //~ Constructors ----------------------------------------------------------- @@ -60,6 +60,12 @@ public Object executeTask(final User user, final String taskdomain, final Object body, final ServerActionParameter... params) throws RemoteException { + if (LOG.isDebugEnabled()) { + LOG.debug("executing task '" + taskname + "' with " + params.length + + " server action parameters and body object: " + (body != null) + + " for user '" + user.getName() + "'"); + } + return ((Sirius.server.middleware.interfaces.domainserver.ActionService)activeLocalServers.get(taskdomain)) .executeTask(user, taskname, body, params); } diff --git a/src/main/java/de/cismet/cids/server/actions/BandwidthTestAction.java b/src/main/java/de/cismet/cids/server/actions/BandwidthTestAction.java index 4d94fa5f..9dd14be3 100644 --- a/src/main/java/de/cismet/cids/server/actions/BandwidthTestAction.java +++ b/src/main/java/de/cismet/cids/server/actions/BandwidthTestAction.java @@ -8,9 +8,12 @@ package de.cismet.cids.server.actions; import Sirius.server.middleware.impls.domainserver.DomainServerImpl; -import Sirius.server.middleware.interfaces.domainserver.MetaService; import Sirius.server.property.ServerProperties; +import de.cismet.cidsx.base.types.Type; + +import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; + /** * DOCUMENT ME! * @@ -20,50 +23,83 @@ @org.openide.util.lookup.ServiceProvider(service = ServerAction.class) public class BandwidthTestAction extends DownloadFileAction { - //~ Static fields/initializers --------------------------------------------- + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new BandwidthTestAction object. + */ + public BandwidthTestAction() { + super(); - public static final String TASK_NAME = "bandwidthTest"; + this.actionInfo.setActionKey("bandwidthTest"); + this.actionInfo.setName("Bandwidth Test"); + this.actionInfo.setDescription("Bandwidth Test"); + + this.actionInfo.getParameterDescription().get(0).setType(Type.INTEGER); + this.actionInfo.getParameterDescription().get(0).setKey("fileSizeInMb"); + this.actionInfo.getParameterDescription().get(0).setDescription("Size of the test file in MB"); + + this.actionInfo.getBodyDescription().setType(Type.INTEGER); + this.actionInfo.getBodyDescription().setKey("fileSizeInMb"); + this.actionInfo.getBodyDescription() + .setDescription("Deprecated, use 'fileSizeInMb' server action parameter instead"); + } //~ Methods ---------------------------------------------------------------- @Override - public String getTaskName() { - return TASK_NAME; + public final String getTaskName() { + return "bandwidthTest"; } @Override - public Object execute(final Object body, final ServerActionParameter... params) { - if (body == null) { - throw new RuntimeException("The body is missing."); - } else if (!(body instanceof Integer)) { - throw new RuntimeException("Wrong type for body, have to be an Integer."); - } else { - final Integer fileSizeInMb = (Integer)body; - - final ServerProperties serverProps = DomainServerImpl.getServerProperties(); - final String serverRespath = serverProps.getServerResourcesBasePath(); - final String s = serverProps.getFileSeparator(); - final String filePath = "/bandwidthTest/" + fileSizeInMb.toString() + "MB.zip"; - final Object ret; - if ("/".equals(s)) { - ret = super.execute(serverRespath + filePath); - } else { - ret = super.execute(serverRespath + filePath.replace("/", s)); + public GenericResourceWithContentType execute(final Object body, final ServerActionParameter... params) { + int fileSizeInMb = -1; + if ((params != null) && (params.length > 0)) { + for (final ServerActionParameter sap : params) { + if (sap.getKey().equalsIgnoreCase("fileSizeInMb")) { + fileSizeInMb = Integer.valueOf(sap.getValue().toString()); + break; + } else { + LOG.warn("unsupported server action parameter:" + sap.toString()); + } } - if (ret == null) { - throw new RuntimeException("Testfile not found."); + } + + if (fileSizeInMb == -1) { + LOG.warn("client did not provide ServerActionParameter 'fileSizeInMb'"); + if (body != null) { + fileSizeInMb = Integer.valueOf(body.toString()); + final String message = "client provided 'fileSizeInMb' as server action " + + "nor as body parameter!"; + throw new RuntimeException(message); } - return ret; } - } - @Override - public MetaService getMetaService() { - return ms; - } + final ServerProperties serverProps = DomainServerImpl.getServerProperties(); + final String serverRespath = serverProps.getServerResourcesBasePath(); + final String s = serverProps.getFileSeparator(); + final String filePath = "/bandwidthTest/" + fileSizeInMb + "MB.zip"; + final GenericResourceWithContentType ret; + if ("/".equals(s)) { + final ServerActionParameter pathParameter = new ServerActionParameter( + PARAMETER_TYPE.FILEPATH.name(), + serverRespath + + filePath); + ret = super.execute(null, pathParameter); + } else { + final ServerActionParameter pathParameter = new ServerActionParameter( + PARAMETER_TYPE.FILEPATH.name(), + serverRespath + + filePath.replace("/", s)); + ret = super.execute(null, pathParameter); + } + if (ret == null) { + final String message = "Testfile '" + serverRespath + "' not found."; + LOG.error(message); + throw new RuntimeException(message); + } - @Override - public void setMetaService(final MetaService service) { - ms = service; + return ret; } } diff --git a/src/main/java/de/cismet/cids/server/actions/DefaultScheduledServerActionTestImpl.java b/src/main/java/de/cismet/cids/server/actions/DefaultScheduledServerActionTestImpl.java index 8fbd2327..47202d3c 100644 --- a/src/main/java/de/cismet/cids/server/actions/DefaultScheduledServerActionTestImpl.java +++ b/src/main/java/de/cismet/cids/server/actions/DefaultScheduledServerActionTestImpl.java @@ -5,11 +5,6 @@ * ... and it just works. * ****************************************************/ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package de.cismet.cids.server.actions; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/de/cismet/cids/server/actions/DownloadFileAction.java b/src/main/java/de/cismet/cids/server/actions/DownloadFileAction.java index ff8f6b64..a498994f 100644 --- a/src/main/java/de/cismet/cids/server/actions/DownloadFileAction.java +++ b/src/main/java/de/cismet/cids/server/actions/DownloadFileAction.java @@ -7,55 +7,150 @@ ****************************************************/ package de.cismet.cids.server.actions; -import Sirius.server.middleware.impls.proxy.ProxyImpl; import Sirius.server.middleware.interfaces.domainserver.MetaService; import Sirius.server.middleware.interfaces.domainserver.MetaServiceStore; import org.apache.log4j.Logger; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.LinkedList; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import de.cismet.cidsx.base.types.Type; + +import de.cismet.cidsx.server.actions.RestApiCidsServerAction; +import de.cismet.cidsx.server.api.types.ActionInfo; +import de.cismet.cidsx.server.api.types.ActionParameterInfo; +import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; /** * DOCUMENT ME! * * @author jruiz * @version $Revision$, $Date$ */ -@org.openide.util.lookup.ServiceProvider(service = ServerAction.class) -public class DownloadFileAction implements ServerAction, MetaServiceStore { +@org.openide.util.lookup.ServiceProvider(service = RestApiCidsServerAction.class) +public class DownloadFileAction implements RestApiCidsServerAction, MetaServiceStore { //~ Static fields/initializers --------------------------------------------- - private static final transient Logger LOG = Logger.getLogger(ProxyImpl.class); + protected static final Logger LOG = Logger.getLogger(DownloadFileAction.class); + + public static final String TASK_NAME = "downloadFile"; + + //~ Enums ------------------------------------------------------------------ + + /** + * DOCUMENT ME! + * + * @version $Revision$, $Date$ + */ + public enum PARAMETER_TYPE { + + //~ Enum constants ----------------------------------------------------- + + FILEPATH + } //~ Instance fields -------------------------------------------------------- + protected final ActionInfo actionInfo; + MetaService ms; + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new DownloadFileAction object. + */ + public DownloadFileAction() { + actionInfo = new ActionInfo(); + actionInfo.setName("Downlad File"); + actionInfo.setActionKey(TASK_NAME); + actionInfo.setDescription("Downloads a remote file from the server."); + + final List parameterDescriptions = new LinkedList(); + final ActionParameterInfo pathParameterDescription = new ActionParameterInfo(); + pathParameterDescription.setKey(PARAMETER_TYPE.FILEPATH.name()); + pathParameterDescription.setType(Type.STRING); + pathParameterDescription.setDescription("Absolute local path of the file to be downloaded"); + parameterDescriptions.add(pathParameterDescription); + actionInfo.setParameterDescription(parameterDescriptions); + + final ActionParameterInfo bodyDescription = new ActionParameterInfo(); + bodyDescription.setKey("body"); + bodyDescription.setType(Type.STRING); + bodyDescription.setMediaType(MediaType.TEXT_PLAIN); + bodyDescription.setDescription("Deprecated body parameter, use server action parameter 'filename' instead!"); + actionInfo.setBodyDescription(bodyDescription); + + final ActionParameterInfo returnDescription = new ActionParameterInfo(); + returnDescription.setKey("return"); + returnDescription.setType(Type.BYTE); + returnDescription.setMediaType(MediaType.WILDCARD); + returnDescription.setDescription("Return value is the file byte stream"); + actionInfo.setResultDescription(returnDescription); + } + //~ Methods ---------------------------------------------------------------- @Override public String getTaskName() { - return "downloadFile"; + return TASK_NAME; } @Override - public Object execute(final Object body, final ServerActionParameter... params) { - System.out.println("Ausführen von DownloadFileAction"); - for (final ServerActionParameter sap : params) { - System.out.println(sap); + public GenericResourceWithContentType execute(final Object body, + final ServerActionParameter... params) { + if (LOG.isDebugEnabled()) { + LOG.debug("executing '" + this.getTaskName() + "' with " + + params.length + " server action parameters and body object: " + (body != null)); } try { - final File file = new File((String)body); - final FileInputStream fin = new FileInputStream(file); - final byte[] fileContent = new byte[(int)file.length()]; - fin.read(fileContent); - return fileContent; - } catch (IOException ex) { - LOG.error(ex, ex); - return null; + Path path = null; + if (params.length > 0) { + for (final ServerActionParameter sap : params) { + if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.FILEPATH.name())) { + path = Paths.get(sap.getValue().toString()); + break; + } else { + LOG.warn("unsupported server action parameter:" + sap.toString()); + } + } + } + + if (path == null) { + LOG.warn("client did not provide ServerActionParameter '" + PARAMETER_TYPE.FILEPATH.name() + "'"); + if (body != null) { + path = Paths.get(body.toString()); + LOG.warn("client provided '" + PARAMETER_TYPE.FILEPATH.name() + "' as body parameter!"); + } + } + + String contentType = Files.probeContentType(path); + contentType = (contentType != null) ? contentType : MediaType.APPLICATION_OCTET_STREAM; + + // FIXME: not very efficient for large files -> out of memory! + // return output stream instead?! + final byte[] fileContent = Files.readAllBytes(path); + + LOG.info("File '" + path + "' of type '" + contentType + "' with " + + fileContent.length + " bytes loaded"); + + final GenericResourceWithContentType ressource = new GenericResourceWithContentType( + contentType, + fileContent); + + return ressource; + } catch (Throwable ex) { + final String message = "Could not download file: " + ex.getMessage(); + LOG.error(message, ex); + throw new RuntimeException(message, ex); + // return null; } } @@ -68,4 +163,9 @@ public MetaService getMetaService() { public void setMetaService(final MetaService service) { ms = service; } + + @Override + public ActionInfo getActionInfo() { + return this.actionInfo; + } } diff --git a/src/main/java/de/cismet/cids/server/actions/HttpTunnelAction.java b/src/main/java/de/cismet/cids/server/actions/HttpTunnelAction.java index be866ffc..a034b789 100644 --- a/src/main/java/de/cismet/cids/server/actions/HttpTunnelAction.java +++ b/src/main/java/de/cismet/cids/server/actions/HttpTunnelAction.java @@ -22,6 +22,18 @@ import java.net.URL; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import de.cismet.cidsx.base.types.MediaTypes; +import de.cismet.cidsx.base.types.Type; + +import de.cismet.cidsx.server.actions.RestApiCidsServerAction; +import de.cismet.cidsx.server.api.types.ActionInfo; +import de.cismet.cidsx.server.api.types.ActionParameterInfo; +import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; import de.cismet.commons.security.AccessHandler; import de.cismet.commons.security.exceptions.BadHttpStatusCodeException; @@ -34,11 +46,13 @@ * @author thorsten * @version $Revision$, $Date$ */ -@org.openide.util.lookup.ServiceProvider(service = ServerAction.class) -public class HttpTunnelAction implements UserAwareServerAction { +@org.openide.util.lookup.ServiceProvider(service = RestApiCidsServerAction.class) +public class HttpTunnelAction implements RestApiCidsServerAction, UserAwareServerAction { //~ Static fields/initializers --------------------------------------------- + public static final String TASK_NAME = "httpTunnelAction"; + private static final transient org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger( HttpTunnelAction.class); @@ -64,10 +78,75 @@ public enum PARAMETER_TYPE { //~ Instance fields -------------------------------------------------------- + protected final ActionInfo actionInfo; private User user = null; + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new HttpTunnelAction object. + */ + public HttpTunnelAction() { + actionInfo = new ActionInfo(); + actionInfo.setName("HTTP Tunnel Action"); + actionInfo.setActionKey(TASK_NAME); + actionInfo.setDescription("Tunnels a HTTP Request"); + + final List parameterDescriptions = new LinkedList(); + ActionParameterInfo parameterDescription; + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(PARAMETER_TYPE.URL.name()); + parameterDescription.setType(Type.JAVA_CLASS); + parameterDescription.setAdditionalTypeInfo(URL.class.getName()); + parameterDescription.setDescription("REQUEST URL"); + parameterDescriptions.add(parameterDescription); + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(PARAMETER_TYPE.METHOD.name()); + parameterDescription.setType(Type.JAVA_CLASS); + parameterDescription.setAdditionalTypeInfo(AccessHandler.ACCESS_METHODS.class.getName()); + parameterDescription.setDescription("REQUEST METHOD, e.g. GET"); + parameterDescriptions.add(parameterDescription); + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(PARAMETER_TYPE.METHOD.name()); + parameterDescription.setType(Type.JAVA_CLASS); + parameterDescription.setAdditionalTypeInfo(AccessHandler.ACCESS_METHODS.class.getName()); + parameterDescription.setDescription("REQUEST METHOD, e.g. GET"); + parameterDescriptions.add(parameterDescription); + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(PARAMETER_TYPE.OPTIONS.name()); + parameterDescription.setType(Type.JAVA_CLASS); + parameterDescription.setAdditionalTypeInfo(HashMap.class.getName()); + parameterDescription.setDescription("REQUEST OPTIONS"); + parameterDescriptions.add(parameterDescription); + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(PARAMETER_TYPE.CREDENTIALS.name()); + parameterDescription.setType(Type.JAVA_CLASS); + parameterDescription.setAdditionalTypeInfo(HashMap.class.getName()); + parameterDescription.setDescription("REQUEST OPTIONS"); + parameterDescriptions.add(parameterDescription); + + actionInfo.setParameterDescription(parameterDescriptions); + + final ActionParameterInfo returnDescription = new ActionParameterInfo(); + returnDescription.setKey("return"); + returnDescription.setType(Type.BYTE); + returnDescription.setArray(true); + returnDescription.setMediaType(MediaType.APPLICATION_OCTET_STREAM); + actionInfo.setResultDescription(returnDescription); + } + //~ Methods ---------------------------------------------------------------- + @Override + public ActionInfo getActionInfo() { + return this.actionInfo; + } + /** * DOCUMENT ME! * @@ -79,7 +158,7 @@ public enum PARAMETER_TYPE { * @throws RuntimeException DOCUMENT ME! */ @Override - public Object execute(final Object body, final ServerActionParameter... params) { + public GenericResourceWithContentType execute(final Object body, final ServerActionParameter... params) { String request = ""; URL url = null; try { @@ -89,19 +168,33 @@ public Object execute(final Object body, final ServerActionParameter... params) for (final ServerActionParameter sap : params) { if (sap != null) { - if (sap.getKey().equals(PARAMETER_TYPE.URL.toString())) { - url = (URL)sap.getValue(); - } else if (sap.getKey().equals(PARAMETER_TYPE.METHOD.toString())) { - method = (AccessHandler.ACCESS_METHODS)sap.getValue(); - } else if (sap.getKey().equals(PARAMETER_TYPE.REQUEST.toString())) { - request = (String)sap.getValue(); - } else if (sap.getKey().equals(PARAMETER_TYPE.OPTIONS.toString()) && (sap.getValue() != null)) { - options = (HashMap)sap.getValue(); - } else if (sap.getKey().equals(PARAMETER_TYPE.CREDENTIALS.toString()) && (sap.getValue() != null)) { - credentials = (HashMap)sap.getValue(); + final Object paramValue = sap.getValue(); + if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.URL.toString())) { + if (paramValue instanceof URL) { + url = (URL)paramValue; + } else { + url = new URL(paramValue.toString()); + } + } else if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.METHOD.toString())) { + if (paramValue instanceof AccessHandler.ACCESS_METHODS) { + method = (AccessHandler.ACCESS_METHODS)paramValue; + } else { + method = AccessHandler.ACCESS_METHODS.valueOf(paramValue.toString()); + } + } else if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.REQUEST.toString())) { + request = paramValue.toString(); + } else if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.OPTIONS.toString()) + && (sap.getValue() != null)) { + options = (HashMap)paramValue; + } else if (sap.getKey().equalsIgnoreCase(PARAMETER_TYPE.CREDENTIALS.toString()) + && (sap.getValue() != null)) { + credentials = (HashMap)paramValue; + } else { + LOG.warn("ignoring unsupported parameter '" + sap.getKey() + "' = " + paramValue); } } } + AccessHandler.ACCESS_METHODS notunnelmethod; if (method == AccessHandler.ACCESS_METHODS.GET_REQUEST) { notunnelmethod = AccessHandler.ACCESS_METHODS.GET_REQUEST_NO_TUNNEL; @@ -148,19 +241,23 @@ public Object execute(final Object body, final ServerActionParameter... params) LOG.info(message); } - return result; + return new GenericResourceWithContentType(MediaType.APPLICATION_OCTET_STREAM, result); } catch (final BadHttpStatusCodeException badStatusCodeEx) { final String errorinfo = ("Problem during HttpTunnelAction(" + url + "=, request=" + request + ")"); if (LOG.isDebugEnabled()) { - LOG.debug(errorinfo + "\n" + badStatusCodeEx.getMessage()); + LOG.error(errorinfo + "\n" + badStatusCodeEx.getMessage(), badStatusCodeEx); } return null; } catch (final CannotReadFromURLException exception) { - return exception; + final String errorinfo = ("Problem during HttpTunnelAction(" + url + "=, request=" + request + ")"); + if (LOG.isDebugEnabled()) { + LOG.error(errorinfo + "\n" + exception.getMessage(), exception); + } + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } catch (final Exception exception) { final String errorinfo = ("Problem during HttpTunnelAction(" + url + "=, request=" + request + ")"); if (LOG.isDebugEnabled()) { - LOG.debug(errorinfo + "\n" + exception.getMessage()); + LOG.error(errorinfo + "\n" + exception.getMessage(), exception); } throw new RuntimeException(errorinfo, exception); } @@ -183,6 +280,6 @@ public void setUser(final User user) { */ @Override public String getTaskName() { - return "httpTunnelAction"; + return TASK_NAME; } } diff --git a/src/main/java/de/cismet/cids/server/actions/PasswordSwitcherAdminAction.java b/src/main/java/de/cismet/cids/server/actions/PasswordSwitcherAdminAction.java index d8d4e2ed..6efef7e5 100644 --- a/src/main/java/de/cismet/cids/server/actions/PasswordSwitcherAdminAction.java +++ b/src/main/java/de/cismet/cids/server/actions/PasswordSwitcherAdminAction.java @@ -5,10 +5,6 @@ * ... and it just works. * ****************************************************/ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package de.cismet.cids.server.actions; import Sirius.server.middleware.impls.domainserver.DomainServerImpl; @@ -25,13 +21,24 @@ import java.sql.SQLException; import java.sql.Statement; +import java.util.LinkedList; +import java.util.List; + +import de.cismet.cidsx.base.types.MediaTypes; +import de.cismet.cidsx.base.types.Type; + +import de.cismet.cidsx.server.actions.RestApiCidsServerAction; +import de.cismet.cidsx.server.api.types.ActionInfo; +import de.cismet.cidsx.server.api.types.ActionParameterInfo; +import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; + /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ -@org.openide.util.lookup.ServiceProvider(service = ServerAction.class) -public class PasswordSwitcherAdminAction implements UserAwareServerAction { +@org.openide.util.lookup.ServiceProvider(service = RestApiCidsServerAction.class) +public class PasswordSwitcherAdminAction implements UserAwareServerAction, RestApiCidsServerAction { //~ Static fields/initializers --------------------------------------------- @@ -55,33 +62,88 @@ public enum ParameterType { //~ Instance fields -------------------------------------------------------- + protected final ActionInfo actionInfo; + private User user; + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new PasswordSwitcherAdminAction object. + */ + public PasswordSwitcherAdminAction() { + actionInfo = new ActionInfo(); + actionInfo.setName("Password Switcher Admin Action"); + actionInfo.setActionKey(TASK_NAME); + actionInfo.setDescription("Password Switcher Admin Action"); + + final List parameterDescriptions = new LinkedList(); + ActionParameterInfo parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(ParameterType.LOGIN_NAME.name()); + parameterDescription.setType(Type.STRING); + parameterDescription.setDescription("Name of the user"); + parameterDescriptions.add(parameterDescription); + + parameterDescription = new ActionParameterInfo(); + parameterDescription.setKey(ParameterType.RECOVERY_TIMER.name()); + parameterDescription.setType(Type.INTEGER); + parameterDescription.setDescription("Recovery Timer"); + parameterDescriptions.add(parameterDescription); + + actionInfo.setParameterDescription(parameterDescriptions); + + final ActionParameterInfo returnDescription = new ActionParameterInfo(); + returnDescription.setKey("return"); + returnDescription.setType(Type.JAVA_SERIALIZABLE); + returnDescription.setMediaType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT); + returnDescription.setDescription("Returns only exceptions."); + actionInfo.setResultDescription(returnDescription); + } + //~ Methods ---------------------------------------------------------------- @Override - public Object execute(final Object body, final ServerActionParameter... params) { + public GenericResourceWithContentType execute(final Object body, final ServerActionParameter... params) { String loginNameToSwitch = null; Integer recoveryTimer = null; for (final ServerActionParameter param : params) { - if (ParameterType.LOGIN_NAME.toString().equals(param.getKey().toString())) { - loginNameToSwitch = (String)param.getValue(); - } else if (ParameterType.RECOVERY_TIMER.toString().equals(param.getKey().toString())) { - recoveryTimer = (Integer)param.getValue(); + final Object paramValue = param.getValue(); + + if (ParameterType.LOGIN_NAME.name().equalsIgnoreCase(param.getKey())) { + loginNameToSwitch = paramValue.toString(); + } else if (ParameterType.RECOVERY_TIMER.name().equalsIgnoreCase(param.getKey())) { + if (int.class.isAssignableFrom(paramValue.getClass()) + || Integer.class.isAssignableFrom(paramValue.getClass())) { + recoveryTimer = (Integer)paramValue; + } else { + recoveryTimer = Integer.parseInt(paramValue.toString()); + } + } else { + LOG.warn("unsupported server action parameter '" + param.getKey() + + "' = " + paramValue); } } if (loginNameToSwitch == null) { - return new Exception("Parameter '" + ParameterType.LOGIN_NAME.toString() + "' not set"); + final Exception exception = new Exception("Parameter '" + ParameterType.LOGIN_NAME.toString() + + "' not set"); + LOG.error(exception.getMessage()); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } + if (recoveryTimer == null) { - return new Exception("Parameter '" + ParameterType.RECOVERY_TIMER.toString() + "' not set"); + final Exception exception = new Exception("Parameter '" + ParameterType.RECOVERY_TIMER.toString() + + "' not set"); + LOG.error(exception.getMessage()); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } try { if (!getUser().isAdmin()) { - return new Exception("Only admin Users are allowed to switch passwords !"); + final Exception exception = new Exception("Only admin Users are allowed to switch passwords !"); + LOG.error(exception.getMessage()); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } final Statement s = DomainServerImpl.getServerInstance() @@ -97,11 +159,15 @@ public Object execute(final Object body, final ServerActionParameter... params) ResultSet rs = s.executeQuery(stmts.getPasswordSwitcherAdminActionSelectUserStmt(loginNameToSwitch)); if (!rs.next()) { - return new Exception("User '" + loginNameToSwitch + "' not found!"); + final Exception exception = new Exception("User '" + loginNameToSwitch + "' not found!"); + LOG.error(exception.getMessage()); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } rs = s.executeQuery(stmts.getPasswordSwitcherAdminActionSelectUserStmt(adminLogin)); if (!rs.next()) { - return new Exception("User '" + adminLogin + "' not found!"); + final Exception exception = new Exception("User '" + adminLogin + "' not found!"); + LOG.error(exception.getMessage()); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, exception); } s.executeUpdate(stmts.getPasswordSwitcherAdminActionChangeAndBackupStmt(loginNameToSwitch, adminLogin)); @@ -115,7 +181,7 @@ public Object execute(final Object body, final ServerActionParameter... params) return null; } catch (final SQLException ex) { LOG.error("error while executing sql statement", ex); - return new Exception(ex.getMessage(), ex); + return new GenericResourceWithContentType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT, ex); } } @@ -133,4 +199,9 @@ public User getUser() { public void setUser(final User user) { this.user = user; } + + @Override + public ActionInfo getActionInfo() { + return this.actionInfo; + } } diff --git a/src/main/java/de/cismet/cids/server/actions/ServerActionParameter.java b/src/main/java/de/cismet/cids/server/actions/ServerActionParameter.java index c5dedb7d..e6dc2d20 100644 --- a/src/main/java/de/cismet/cids/server/actions/ServerActionParameter.java +++ b/src/main/java/de/cismet/cids/server/actions/ServerActionParameter.java @@ -7,8 +7,14 @@ ****************************************************/ package de.cismet.cids.server.actions; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import lombok.Data; + import java.io.Serializable; +import java.util.Map; + import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.annotation.XmlRootElement; @@ -16,10 +22,13 @@ /** * DOCUMENT ME! * + * @param + * * @author jruiz * @version $Revision$, $Date$ */ @XmlRootElement +@Data public class ServerActionParameter implements Serializable { //~ Instance fields -------------------------------------------------------- @@ -27,37 +36,30 @@ public class ServerActionParameter implements Serializable { private final String key; private final T value; - //~ Constructors ----------------------------------------------------------- - - /** - * Creates a new ServerActionParameter object. - * - * @param key DOCUMENT ME! - * @param value DOCUMENT ME! - */ - public ServerActionParameter(final String key, final T value) { - this.key = key; - this.value = value; - } - //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * - * @return DOCUMENT ME! - */ - public String getKey() { - return key; - } - - /** - * DOCUMENT ME! + * @param params DOCUMENT ME! * * @return DOCUMENT ME! + * + * @throws IllegalArgumentException DOCUMENT ME! */ - public T getValue() { - return value; + @JsonIgnore + public static ServerActionParameter[] fromMVMap(final MultivaluedMap params) { + if (params == null) { + throw new IllegalArgumentException("Params must be non null."); + } + int i = 0; + final ServerActionParameter[] ret = new ServerActionParameter[params.size()]; + for (final String key : params.keySet()) { + for (final String value : params.get(key)) { + ret[i++] = new ServerActionParameter(key, value); + } + } + return ret; } /** @@ -69,16 +71,16 @@ public T getValue() { * * @throws IllegalArgumentException DOCUMENT ME! */ - public static ServerActionParameter[] fromMVMap(final MultivaluedMap params) { + @JsonIgnore + public static ServerActionParameter[] fromMap(final Map params) { if (params == null) { throw new IllegalArgumentException("Params must be non null."); } int i = 0; final ServerActionParameter[] ret = new ServerActionParameter[params.size()]; for (final String key : params.keySet()) { - for (final String value : params.get(key)) { - ret[i++] = new ServerActionParameter(key, value); - } + final Object value = params.get(key); + ret[i++] = new ServerActionParameter(key, value); } return ret; } diff --git a/src/main/java/de/cismet/cidsx/client/connector/RESTfulInterfaceConnector.java b/src/main/java/de/cismet/cidsx/client/connector/RESTfulInterfaceConnector.java index ad9d267b..b51a0a91 100644 --- a/src/main/java/de/cismet/cidsx/client/connector/RESTfulInterfaceConnector.java +++ b/src/main/java/de/cismet/cidsx/client/connector/RESTfulInterfaceConnector.java @@ -2382,7 +2382,7 @@ public Object executeTask(final User user, if (body != null) { try { if (LOG.isDebugEnabled()) { - LOG.debug("creating Multi Part Form Data '" + MediaType.APPLICATION_OCTET_STREAM_TYPE + "'"); + LOG.debug("creating Multi Part Form Data '" + MediaType.APPLICATION_OCTET_STREAM + "'"); } final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(bos); diff --git a/src/main/java/de/cismet/cidsx/server/actions/RestApiCidsServerAction.java b/src/main/java/de/cismet/cidsx/server/actions/RestApiCidsServerAction.java new file mode 100644 index 00000000..de24aa8f --- /dev/null +++ b/src/main/java/de/cismet/cidsx/server/actions/RestApiCidsServerAction.java @@ -0,0 +1,34 @@ +/*************************************************** +* +* cismet GmbH, Saarbruecken, Germany +* +* ... and it just works. +* +****************************************************/ +package de.cismet.cidsx.server.actions; + +import de.cismet.cids.server.actions.ServerAction; +import de.cismet.cids.server.actions.ServerActionParameter; + +import de.cismet.cidsx.server.api.types.ActionInfo; +import de.cismet.cidsx.server.api.types.GenericResourceWithContentType; + +/** + * A Lookupable Server Action that provides ActionInfo. + * + * @author Pascal Dihé + * @version $Revision$, $Date$ + */ +public interface RestApiCidsServerAction extends ServerAction { + + //~ Methods ---------------------------------------------------------------- + + /** + * Returns ActionInfo describing the (body) parameters and return type of the ActionInfo instance. + * + * @return SearchInfo of the Search instance + */ + ActionInfo getActionInfo(); + @Override + GenericResourceWithContentType execute(Object body, ServerActionParameter... params); +} diff --git a/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerActionFactory.java b/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerActionFactory.java new file mode 100644 index 00000000..7182e4c9 --- /dev/null +++ b/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerActionFactory.java @@ -0,0 +1,411 @@ +/*************************************************** +* +* cismet GmbH, Saarbruecken, Germany +* +* ... and it just works. +* +****************************************************/ +package de.cismet.cidsx.server.api.types.legacy; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.ClassUtils; +import org.apache.log4j.Logger; + +import org.openide.util.Lookup; + +import java.io.InputStream; +import java.io.ObjectInputStream; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import de.cismet.cids.server.actions.ServerAction; +import de.cismet.cids.server.actions.ServerActionParameter; + +import de.cismet.cidsx.base.types.MediaTypes; +import de.cismet.cidsx.base.types.Type; + +import de.cismet.cidsx.server.actions.RestApiCidsServerAction; +import de.cismet.cidsx.server.api.types.ActionInfo; +import de.cismet.cidsx.server.api.types.ActionParameterInfo; +import de.cismet.cidsx.server.api.types.ActionTask; + +/** + * Helper Methods for dealing with ServerAction and and ActionInfo. + * + * @author Pascal Dihé + * @version $Revision$, $Date$ + */ +public class ServerActionFactory { + + //~ Static fields/initializers --------------------------------------------- + + private static final transient Logger LOG = Logger.getLogger(ServerActionFactory.class); + + private static ServerActionFactory factory = null; + + private static final ObjectMapper MAPPER = new ObjectMapper(new JsonFactory()); + + //~ Instance fields -------------------------------------------------------- + + private final HashMap> serverActionClassMap = + new HashMap>(); + private final HashMap serverActionMap = new HashMap(); + private final HashMap serverActionInfoMap = new HashMap(); + + private boolean cacheFilled = false; + + private final ActionParameterInfo defaultBodyDescription; + private final ActionParameterInfo defaultReturnDescription; + + //~ Constructors ----------------------------------------------------------- + + /** + * Creates a new ServerActionFactory object. + */ + private ServerActionFactory() { + defaultBodyDescription = new ActionParameterInfo(); + defaultBodyDescription.setKey("body"); + defaultBodyDescription.setDescription("Body Part Parameter (usually a file) of the Server Action."); + defaultBodyDescription.setType(Type.JAVA_SERIALIZABLE); + defaultBodyDescription.setMediaType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT); + defaultBodyDescription.setArray(false); + + defaultReturnDescription = new ActionParameterInfo(); + defaultBodyDescription.setDescription("Return value of the Server Action."); + defaultReturnDescription.setKey("return"); + defaultReturnDescription.setType(Type.JAVA_SERIALIZABLE); + defaultReturnDescription.setMediaType(MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT); + defaultReturnDescription.setArray(false); + + this.fillCache(); + } + + //~ Methods ---------------------------------------------------------------- + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static final ServerActionFactory getFactory() { + if (factory == null) { + factory = new ServerActionFactory(); + } + + return factory; + } + + /** + * Inspects a ServerAction Instance and tries to automatically derive a proper ActionInfo object. + * + * @param cidsServerAction server action to be inspected + * + * @return action info or null if the inspection fails + */ + public ActionInfo actionInfoFromServerAction(final ServerAction cidsServerAction) { + try { + final Class serverActionClass = cidsServerAction.getClass(); + LOG.info("processing ServerAction '" + serverActionClass.getName() + "'"); + + final ActionInfo actionInfo = new ActionInfo(); + // FIXME: actionKey should be the class name! + // final String actionKey = serverActionClass.getName(); + final String actionKey = cidsServerAction.getTaskName(); + final String name = cidsServerAction.getTaskName(); + final String description = "Cids Server Action '" + name + + "'. Attention: ActionInfo generated automatically, no " + + "information about parameter and return types available!"; + + // that's all. No information about parameters at classs level available! + final LinkedList actionParameterInfos = new LinkedList(); + + final ActionParameterInfo bodyParameterInfo = this.getDefaultBodyDescription(); + final ActionParameterInfo returnParameterInfo = this.getDefaultReturnDescription(); + + actionInfo.setActionKey(actionKey); + actionInfo.setName(serverActionClass.getSimpleName()); + actionInfo.setDescription(description); + actionInfo.setParameterDescription(actionParameterInfos); + actionInfo.setBodyDescription(bodyParameterInfo); + actionInfo.setResultDescription(returnParameterInfo); + + return actionInfo; + } catch (Throwable t) { + LOG.error("could not inspect ServerAction '" + + cidsServerAction.getClass().getName() + "': " + t.getMessage(), + t); + } + + return null; + } + + /** + * Lookups all available Server Actions, collects the respective Action Infos and adds it to the cache. + */ + private void fillCache() { + if (cacheFilled) { + LOG.warn("ServerActionCache already filled"); + } + + final Collection lookupableServerActions = Lookup.getDefault() + .lookupAll(RestApiCidsServerAction.class); + final Collection cidsServerActions = Lookup.getDefault().lookupAll(ServerAction.class); + + LOG.info("loading " + lookupableServerActions.size() + " Lookupable Server Action and trying to inspect " + + cidsServerActions.size() + " cids Server Actions"); + + // process the actions that provide action info + for (final RestApiCidsServerAction lookupableServerAction : lookupableServerActions) { + final ActionInfo actionInfo = lookupableServerAction.getActionInfo(); + final Class serverActionClass = lookupableServerAction.getClass(); + final String actionKey = actionInfo.getActionKey(); + if (LOG.isDebugEnabled()) { + LOG.debug("adding Lookupable Server Action '" + actionKey + "'"); + } + this.serverActionMap.put(actionKey, lookupableServerAction); + this.serverActionClassMap.put(actionKey, serverActionClass); + this.serverActionInfoMap.put(actionKey, new ActionTask(actionInfo)); + } + + // procress the legacy actions + for (final ServerAction cidsServerAction : cidsServerActions) { + // FIXME: should use the class name as action key! + // final String actionKey = cidsServerAction.getClass().getName(); + final String actionKey = cidsServerAction.getTaskName(); + if (!this.serverActionInfoMap.containsKey(actionKey)) { + final ActionInfo actionInfo = this.actionInfoFromServerAction(cidsServerAction); + if (actionInfo != null) { + final Class serverActionClass = cidsServerAction.getClass(); + if (!actionKey.equals(actionInfo.getActionKey())) { + LOG.warn("action key missmatch: '" + actionKey + + "' != '" + actionInfo.getActionKey() + "'!"); + } + + // FIXME: should check against the class name + if (!this.serverActionInfoMap.containsKey(cidsServerAction.getTaskName())) { + if (LOG.isDebugEnabled()) { + LOG.debug("adding Cids Server Action '" + actionKey + "'"); + } + this.serverActionMap.put(actionKey, cidsServerAction); + this.serverActionClassMap.put(actionKey, serverActionClass); + this.serverActionInfoMap.put(actionKey, new ActionTask(actionInfo)); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Cids Server Action '" + actionKey + + "' already registered by Lookupable Server Action."); + } + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Cids Server Action '" + cidsServerAction.getClass().getName() + + "' already registered by Lookupable Server Action."); + } + } + } + + cacheFilled = true; + } + + /** + * Tries to find a cached ActionInfo object of the specified cids server action. + * + * @param actionKey the action key (e.g.java class name) of the action + * + * @return ActionInfo instance or null + */ + public ActionInfo getServerActionInfo(final String actionKey) { + if (!this.serverActionInfoMap.containsKey(actionKey)) { + LOG.warn("could not find ActionInfo for action key '" + actionKey + "'"); + } + + return this.serverActionInfoMap.get(actionKey); + } + + /** + * Tries to find a cached ActionInfo object of the specified cids server action. + * + * @param actionKey the action key (e.g.java class name) of the action + * + * @return ActionInfo instance or null + */ + public ServerAction getServerAction(final String actionKey) { + if (!this.serverActionMap.containsKey(actionKey)) { + LOG.warn("could not find ServerAction for action key '" + actionKey + "'"); + } + + return this.serverActionMap.get(actionKey); + } + + /** + * Returns all cached ServerActionInfos. + * + * @return ServerActionInfo Collection + */ + public List getServerActionInfos() { + return new LinkedList(this.serverActionInfoMap.values()); + } + + /** + * Returns all cached ServerActionInfos. + * + * @return ServerActionInfo Collection + */ + public List getServerActions() { + return new LinkedList(this.serverActionMap.values()); + } + + /** + * Tries to find a cached ServerAction class for the specified cids server action key. + * + * @param actionKey key (e.g. class name) of the server action + * + * @return ServerAction Class or null + */ + public Class getServerActionClass(final String actionKey) { + if (!this.serverActionClassMap.containsKey(actionKey)) { + LOG.warn("could not find legacy action java class for action key '" + actionKey + "'"); + } + + return this.serverActionClassMap.get(actionKey); + } + + /** + * Populates an instance of a ServerAction with parameters from the actionParameters object. + * + * @param actionTask DOCUMENT ME! + * + * @return ServerAction with parameters + */ + public ServerActionParameter[] ServerActionParametersFromActionTask( + final ActionTask actionTask) { + if (LOG.isDebugEnabled()) { + LOG.debug("getting parameters from cids server action '" + actionTask.getActionKey() + "'"); + } + + if ((actionTask.getParameters() == null) || actionTask.getParameters().isEmpty()) { + LOG.warn("no action parameters available for action '" + actionTask.getActionKey() + "'"); + return new ServerActionParameter[0]; + } + + final ServerActionParameter[] actionParameters = ServerActionParameter.fromMap(actionTask.getParameters()); + if (LOG.isDebugEnabled()) { + LOG.debug(actionParameters.length + " action parameters found for cids server action '" + + actionTask.getActionKey() + "'"); + } + if ((actionTask.getParameterDescription() != null) && !actionTask.getParameterDescription().isEmpty()) { + for (int i = 0; i < actionParameters.length; i++) { + final ServerActionParameter actionParameter = actionParameters[i]; + final ActionParameterInfo parameterInfo = actionTask.getActionParameterInfo(actionParameter.getKey()); + if ((parameterInfo != null) && (parameterInfo.getType() == Type.JAVA_SERIALIZABLE)) { + if (parameterInfo.getType() == Type.JAVA_SERIALIZABLE) { + if (LOG.isDebugEnabled()) { + LOG.debug("deserializing binary java object parameter '" + parameterInfo.getKey() + "'"); + } + try { + final Object paramValue = ServerSearchFactory.fromBase64String(actionParameter.getValue() + .toString()); + actionParameters[i] = new ServerActionParameter(actionParameter.getKey(), paramValue); + } catch (Throwable t) { + LOG.warn("could not deserialize binary java object parameter '" + parameterInfo.getKey() + + "': " + t.getMessage(), + t); + } + } + } + } + } + return actionParameters; + } + + /** + * DOCUMENT ME! + * + * @param fileAttachement DOCUMENT ME! + * @param bodyDescription DOCUMENT ME! + * + * @return DOCUMENT ME! + * + * @throws Exception DOCUMENT ME! + */ + public Object bodyObjectFromFileAttachment(final InputStream fileAttachement, + final ActionParameterInfo bodyDescription) throws Exception { + final Object body; + + if (bodyDescription.getMediaType().toLowerCase().equalsIgnoreCase( + MediaTypes.APPLICATION_X_JAVA_SERIALIZED_OBJECT)) { + if (LOG.isDebugEnabled()) { + LOG.debug("deserializing binary java object attachment"); + } + final ObjectInputStream ois = new ObjectInputStream(fileAttachement); + body = ois.readObject(); + if (LOG.isDebugEnabled()) { + LOG.debug("successfully restored java object '" + body.getClass() + "' from binary input file"); + } + } else if (bodyDescription.getMediaType().equalsIgnoreCase(MediaType.APPLICATION_JSON)) { + Class javaClass = Object.class; + try { + if ((bodyDescription.getType() != null) && (bodyDescription.getAdditionalTypeInfo() != null)) { + javaClass = ClassUtils.getClass(bodyDescription.getAdditionalTypeInfo()); + } + } catch (ClassNotFoundException cne) { + LOG.warn("could not find java class for type '" + bodyDescription.getAdditionalTypeInfo() + "'", cne); + } + if (LOG.isDebugEnabled()) { + LOG.debug("deserializing JSON attachment to Java Object '" + javaClass.getSimpleName() + "'"); + } + body = MAPPER.readValue(fileAttachement, javaClass); + } else if (bodyDescription.getMediaType().toLowerCase().contains("text")) { + body = IOUtils.toString(fileAttachement, "UTF-8"); + if (LOG.isDebugEnabled()) { + LOG.debug("deserializing plain text attachment to String: '" + body + "'"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("deserializing byte array attachment from '" + bodyDescription.getMediaType() + "' resource"); + } + body = IOUtils.toByteArray(fileAttachement); + if (body != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("successfully read byte array of length " + ((byte[])body).length); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.warn("no binary body (e.g. file) parameter provided!"); + } + } + } + + return body; + } + + /** + * Generates a default body description, if neither the action implementation nor the client provide information + * about the content type of the body part.
+ * The Default content type if none is specified is application/x-java-object (binary serialized java object). + * + * @return DefaultBodyDescriptio + */ + public ActionParameterInfo getDefaultBodyDescription() { + return defaultBodyDescription; + } + + /** + * Generates a default return description, if the action implementation does not provide information about the + * content type of it's return value.
+ * The Default content type if none is specified is application/x-java-object (binary serialized java object). + * + * @return DefaultReturnDescription + */ + public ActionParameterInfo getDefaultReturnDescription() { + return defaultReturnDescription; + } +} diff --git a/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerSearchFactory.java b/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerSearchFactory.java index b16efee2..738418a6 100644 --- a/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerSearchFactory.java +++ b/src/main/java/de/cismet/cidsx/server/api/types/legacy/ServerSearchFactory.java @@ -110,7 +110,7 @@ public static final ServerSearchFactory getFactory() { } /** - * Inspects a CidsServerSearch Instance and tries to automatically serive a proper SearchInfo object. + * Inspects a CidsServerSearch Instance and tries to automatically derive a proper SearchInfo object. * * @param cidsServerSearch server search to be inspected * @@ -346,7 +346,7 @@ public CidsServerSearch serverSearchInstanceFromSearchParameters( for (final SearchParameter searchParameter : searchParameters) { final String paramKey = searchParameter.getKey(); - final SearchParameterInfo searchParameterInfo = searchInfo.getSearchParameterInfo(paramKey); + final SearchParameterInfo searchParameterInfo = searchInfo.getParameterInfo(paramKey); if (searchParameterInfo == null) { final String message = "could not create instance of cids server search '" + searchInfo.getKey() + "': server search parameter '" @@ -363,7 +363,7 @@ public CidsServerSearch serverSearchInstanceFromSearchParameters( || (searchParameterInfo.getType() == Type.ENTITY_INFO) || (searchParameterInfo.getType() == Type.NODE)) { // FIXME: if required, handle MetaObject, MetaClass and MetaNode - // in custom serializer / deserilaitzer implementation of + // in custom serializer / deserializer implementation of // SearchParameter.class final String message = "The Search Parameter '" + searchParameterInfo.getKey() + "' (" + searchParameterInfo.getType().name() + ") of the cids server search '" @@ -926,7 +926,7 @@ public Map findSearchParameterWrite * * @throws IOException DOCUMENT ME! */ - private static String toBase64String(final Object object) throws IOException { + public static final String toBase64String(final Object object) throws IOException { if (object.getClass().isAssignableFrom(Serializable.class)) { final Serializable serializable = (Serializable)object; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -953,7 +953,7 @@ private static String toBase64String(final Object object) throws IOException { * @throws IOException DOCUMENT ME! * @throws ClassNotFoundException DOCUMENT ME! */ - private static Object fromBase64String(final String s) throws IOException, ClassNotFoundException { + public static final Object fromBase64String(final String s) throws IOException, ClassNotFoundException { final byte[] data = Base64.decode(s); final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); final Object o = ois.readObject();