From e241a5585404c07bea8351c4112be64512ad7fb9 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 16 Sep 2009 14:06:11 +0000 Subject: [PATCH] Security Demo git-svn-id: https://svn.argeo.org/commons/trunk@2937 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../META-INF/MANIFEST.MF | 3 + .../log4j.properties | 28 ++++++++ security/demo/pom.xml | 29 ++++++-- .../META-INF/MANIFEST.MF | 10 ++- .../WEB-INF/security-servlet.xml | 17 +++++ security/modules/pom.xml | 2 +- .../runtime/org.argeo.security.core/pom.xml | 25 ++++--- .../argeo/security/core/ArgeoUserDetails.java | 38 ++++++++-- .../runtime/org.argeo.security.mvc/pom.xml | 36 +++------- .../security/mvc/UsersRolesController.java | 22 ++++++ security/runtime/pom.xml | 3 +- .../META-INF/MANIFEST.MF | 3 +- server/pom.xml | 1 + .../runtime/org.argeo.server.core/.classpath | 7 ++ server/runtime/org.argeo.server.core/.project | 23 ++++++ .../.settings/org.eclipse.jdt.core.prefs | 5 ++ .../.settings/org.maven.ide.eclipse.prefs | 9 +++ server/runtime/org.argeo.server.core/pom.xml | 60 ++++++++++++++++ .../argeo/server/ArgeoServerException.java | 21 ++++++ .../java/org/argeo/server/ServerAnswer.java | 72 +++++++++++++++++++ server/runtime/org.argeo.server.json/pom.xml | 7 ++ .../org/argeo/server/json/mvc/JsonView.java | 40 +++++++---- .../server/json/mvc/JsonViewResolver.java | 18 +++++ server/runtime/pom.xml | 1 + 24 files changed, 413 insertions(+), 67 deletions(-) create mode 100644 security/demo/org.argeo.security.demo.log4j/META-INF/MANIFEST.MF create mode 100644 security/demo/org.argeo.security.demo.log4j/log4j.properties create mode 100644 security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml create mode 100644 security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java create mode 100644 server/runtime/org.argeo.server.core/.classpath create mode 100644 server/runtime/org.argeo.server.core/.project create mode 100644 server/runtime/org.argeo.server.core/.settings/org.eclipse.jdt.core.prefs create mode 100644 server/runtime/org.argeo.server.core/.settings/org.maven.ide.eclipse.prefs create mode 100644 server/runtime/org.argeo.server.core/pom.xml create mode 100644 server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ArgeoServerException.java create mode 100644 server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java create mode 100644 server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonViewResolver.java diff --git a/security/demo/org.argeo.security.demo.log4j/META-INF/MANIFEST.MF b/security/demo/org.argeo.security.demo.log4j/META-INF/MANIFEST.MF new file mode 100644 index 000000000..b96ebfe10 --- /dev/null +++ b/security/demo/org.argeo.security.demo.log4j/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Bundle-SymbolicName: org.argeo.server.demo.log4j +Bundle-Version: 0.1.1.SNAPSHOT +Fragment-Host: com.springsource.org.apache.log4j diff --git a/security/demo/org.argeo.security.demo.log4j/log4j.properties b/security/demo/org.argeo.security.demo.log4j/log4j.properties new file mode 100644 index 000000000..dd02654c2 --- /dev/null +++ b/security/demo/org.argeo.security.demo.log4j/log4j.properties @@ -0,0 +1,28 @@ +log4j.rootLogger=WARN, console + +## Levels +log4j.logger.org.argeo=DEBUG + +log4j.logger.org.hibernate=WARN + +log4j.logger.org.springframework=WARN +log4j.logger.org.springframework.web=DEBUG +#log4j.logger.org.springframework.jms=WARN +#log4j.logger.org.springframework.security=WARN + +log4j.logger.org.apache.activemq=WARN +log4j.logger.org.apache.activemq.transport=WARN +log4j.logger.org.apache.activemq.ActiveMQMessageConsumer=INFO +log4j.logger.org.apache.activemq.ActiveMQMessageProducer=INFO + +log4j.logger.org.apache.catalina=INFO +log4j.logger.org.apache.coyote=INFO +log4j.logger.org.apache.tomcat=INFO + +## Appenders +# console is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# console uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/security/demo/pom.xml b/security/demo/pom.xml index 10fbcb526..7f52d9631 100644 --- a/security/demo/pom.xml +++ b/security/demo/pom.xml @@ -25,18 +25,23 @@ org.argeo.maven.plugins maven-argeo-osgi-plugin - target/exec/server + target/exec org.argeo.osgi.boot + + -clean + + false org.springframework.osgi.extender, org.springframework.osgi.web.extender, org.argeo.dep.osgi.catalina.start, - org.argeo.server.security.webapp + org.argeo.security.webapp ${basedir};in=*;ex=pom.xml;ex=target;ex=.*, ${basedir}/../modules;in=*;ex=pom.xml;ex=target;ex=.*, + ${basedir}/../../server/modules;in=*;ex=pom.xml;ex=target;ex=.*, @@ -44,6 +49,18 @@ + + + org.argeo.commons.security + org.argeo.security.mvc + 0.1.1-SNAPSHOT + + + org.argeo.commons.server + org.argeo.server.json + 0.1.1-SNAPSHOT + + @@ -147,11 +164,11 @@ com.springsource.javax.xml.bind - + + --> diff --git a/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF b/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF index e17384c65..8116c1e4f 100644 --- a/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF +++ b/security/modules/org.argeo.security.webapp/META-INF/MANIFEST.MF @@ -3,4 +3,12 @@ Bundle-SymbolicName: org.argeo.security.webapp Bundle-Version: 0.1.1.SNAPSHOT Import-Package: javax.servlet, javax.servlet.http, - javax.servlet.resources + javax.servlet.resources, + org.argeo.security.mvc, + org.argeo.server.json.mvc, + org.springframework.osgi.web.context.support, + org.springframework.security.userdetails.memory, + org.springframework.web.context, + org.springframework.web.context.support, + org.springframework.web.filter, + org.springframework.web.servlet diff --git a/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml b/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml new file mode 100644 index 000000000..21f95619c --- /dev/null +++ b/security/modules/org.argeo.security.webapp/WEB-INF/security-servlet.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/security/modules/pom.xml b/security/modules/pom.xml index a435223a1..fb9ed5759 100644 --- a/security/modules/pom.xml +++ b/security/modules/pom.xml @@ -9,7 +9,7 @@ org.argeo.security modules bundles - Commons Server Modules + Commons Security Modules diff --git a/security/runtime/org.argeo.security.core/pom.xml b/security/runtime/org.argeo.security.core/pom.xml index 51aca0eac..340e08fc9 100644 --- a/security/runtime/org.argeo.security.core/pom.xml +++ b/security/runtime/org.argeo.security.core/pom.xml @@ -40,14 +40,9 @@ - org.springframework.ldap - org.springframework.ldap - 1.3.0.RELEASE - - - org.springframework.ldap - org.springframework.ldap.core.simple - 1.3.0.RELEASE + org.argeo.dep.osgi + org.argeo.dep.osgi.springframework.ldap + 1.3.0.0002 @@ -56,6 +51,20 @@ org.springframework.security + + + org.slf4j + com.springsource.slf4j.org.apache.commons.logging + + + org.apache.log4j + com.springsource.org.apache.log4j + + + org.slf4j + com.springsource.slf4j.log4j + + org.codehaus.jackson diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java index 1f82ee949..b20bac447 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java @@ -5,9 +5,12 @@ import java.util.Collections; import java.util.List; import org.argeo.security.ArgeoUser; +import org.argeo.security.BasicArgeoUser; import org.argeo.security.UserNature; +import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.User; +import org.springframework.security.userdetails.UserDetails; public class ArgeoUserDetails extends User implements ArgeoUser { private static final long serialVersionUID = 1L; @@ -20,13 +23,10 @@ public class ArgeoUserDetails extends User implements ArgeoUser { throws IllegalArgumentException { super(username, password, true, true, true, true, authorities); this.userNatures = Collections.unmodifiableList(userNatures); - + // Roles - List roles = new ArrayList(); - for (GrantedAuthority authority : getAuthorities()) { - roles.add(authority.getAuthority()); - } - this.roles = Collections.unmodifiableList(roles); + this.roles = Collections.unmodifiableList(addAuthoritiesToRoles( + getAuthorities(), new ArrayList())); } public List getUserNatures() { @@ -36,4 +36,30 @@ public class ArgeoUserDetails extends User implements ArgeoUser { public List getRoles() { return roles; } + + /** The provided list, for chaining using {@link Collections} */ + protected static List addAuthoritiesToRoles( + GrantedAuthority[] authorities, List roles) { + for (GrantedAuthority authority : authorities) { + roles.add(authority.getAuthority()); + } + return roles; + } + + public static BasicArgeoUser createBasicArgeoUser(UserDetails userDetails) { + BasicArgeoUser argeoUser = new BasicArgeoUser(); + argeoUser.setUsername(userDetails.getUsername()); + addAuthoritiesToRoles(userDetails.getAuthorities(), argeoUser + .getRoles()); + return argeoUser; + } + + public static BasicArgeoUser createBasicArgeoUser( + Authentication authentication) { + BasicArgeoUser argeoUser = new BasicArgeoUser(); + argeoUser.setUsername(authentication.getName()); + addAuthoritiesToRoles(authentication.getAuthorities(), argeoUser + .getRoles()); + return argeoUser; + } } diff --git a/security/runtime/org.argeo.security.mvc/pom.xml b/security/runtime/org.argeo.security.mvc/pom.xml index e6644fc83..0fe4c2f51 100644 --- a/security/runtime/org.argeo.security.mvc/pom.xml +++ b/security/runtime/org.argeo.security.mvc/pom.xml @@ -30,7 +30,7 @@ - org.argeo.security.* + org.argeo.security.mvc.* @@ -38,6 +38,13 @@ + + + org.argeo.commons.security + org.argeo.security.core + 0.1.1-SNAPSHOT + + org.springframework @@ -54,32 +61,5 @@ com.springsource.javax.servlet - - - org.springframework.security - org.springframework.security - - - - com.springsource.json - com.springsource.json - 1.0.1.RELEASE - - - org.antlr - com.springsource.org.antlr - - - - - org.springframework.ldap - org.springframework.ldap - 1.3.0.RELEASE - - - org.springframework.ldap - org.springframework.ldap.core.simple - 1.3.0.RELEASE - diff --git a/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java new file mode 100644 index 000000000..7f5334564 --- /dev/null +++ b/security/runtime/org.argeo.security.mvc/src/main/java/org/argeo/security/mvc/UsersRolesController.java @@ -0,0 +1,22 @@ +package org.argeo.security.mvc; + +import org.argeo.security.ArgeoUser; +import org.argeo.security.core.ArgeoUserDetails; +import org.springframework.security.Authentication; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class UsersRolesController { + + @RequestMapping("/getCredentials.security") + @ModelAttribute("getCredentials") + public ArgeoUser getCredentials() { + Authentication authentication = SecurityContextHolder.getContext() + .getAuthentication(); + + return ArgeoUserDetails.createBasicArgeoUser(authentication); + } +} diff --git a/security/runtime/pom.xml b/security/runtime/pom.xml index 960812cfe..ca24e5b3a 100644 --- a/security/runtime/pom.xml +++ b/security/runtime/pom.xml @@ -13,6 +13,7 @@ Commons Security Runtime pom - org.argeo.security.ria + org.argeo.security.core + org.argeo.security.mvc \ No newline at end of file diff --git a/server/modules/org.argeo.server.catalina/META-INF/MANIFEST.MF b/server/modules/org.argeo.server.catalina/META-INF/MANIFEST.MF index 01d0fcca0..78701c1b7 100644 --- a/server/modules/org.argeo.server.catalina/META-INF/MANIFEST.MF +++ b/server/modules/org.argeo.server.catalina/META-INF/MANIFEST.MF @@ -7,4 +7,5 @@ Import-Package: org.springframework.security;resolution:=optional, org.springframework.security.providers;resolution:=optional, org.springframework.security.ui;resolution:=optional, org.springframework.security.ui.savedrequest;resolution:=optional, - org.springframework.security.userdetails;resolution:=optional + org.springframework.security.userdetails;resolution:=optional, + org.springframework.security.context;resolution:=optional diff --git a/server/pom.xml b/server/pom.xml index 57d13d1df..4392f9cfb 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -12,6 +12,7 @@ Commons Server pom + runtime modules \ No newline at end of file diff --git a/server/runtime/org.argeo.server.core/.classpath b/server/runtime/org.argeo.server.core/.classpath new file mode 100644 index 000000000..16f01e2ee --- /dev/null +++ b/server/runtime/org.argeo.server.core/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/runtime/org.argeo.server.core/.project b/server/runtime/org.argeo.server.core/.project new file mode 100644 index 000000000..18565208d --- /dev/null +++ b/server/runtime/org.argeo.server.core/.project @@ -0,0 +1,23 @@ + + + org.argeo.server.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.maven.ide.eclipse.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/server/runtime/org.argeo.server.core/.settings/org.eclipse.jdt.core.prefs b/server/runtime/org.argeo.server.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..2a55b739f --- /dev/null +++ b/server/runtime/org.argeo.server.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Wed Sep 16 10:02:19 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/server/runtime/org.argeo.server.core/.settings/org.maven.ide.eclipse.prefs b/server/runtime/org.argeo.server.core/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..fb7d9a8cd --- /dev/null +++ b/server/runtime/org.argeo.server.core/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Wed Sep 16 10:02:18 CEST 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/server/runtime/org.argeo.server.core/pom.xml b/server/runtime/org.argeo.server.core/pom.xml new file mode 100644 index 000000000..51d1267b4 --- /dev/null +++ b/server/runtime/org.argeo.server.core/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + + org.argeo.commons.server + runtime + 0.1.1-SNAPSHOT + .. + + org.argeo.server.core + Commons Server Core + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + ${version.maven-bundle-plugin} + + + + org.argeo.server.* + + + + + + + + + + org.apache.commons + com.springsource.org.apache.commons.io + + + + + org.springframework + org.springframework.web.servlet + + + + + javax.servlet + com.springsource.javax.servlet + + + + diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ArgeoServerException.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ArgeoServerException.java new file mode 100644 index 000000000..f8e3fc4fc --- /dev/null +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ArgeoServerException.java @@ -0,0 +1,21 @@ +package org.argeo.server; + +public class ArgeoServerException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public ArgeoServerException() { + } + + public ArgeoServerException(String message) { + super(message); + } + + public ArgeoServerException(Throwable cause) { + super(cause); + } + + public ArgeoServerException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java new file mode 100644 index 000000000..c3e747608 --- /dev/null +++ b/server/runtime/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java @@ -0,0 +1,72 @@ +package org.argeo.server; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; + +/** Answer to an execution of a remote service which performed changes. */ +public class ServerAnswer { + public final static String OK = "OK"; + public final static String ERROR = "ERROR"; + + private String status = OK; + private String message = ""; + + /** Canonical constructor */ + public ServerAnswer(String status, String message) { + setStatus(status); + if (message == null) + throw new ArgeoServerException("Message cannot be null"); + this.message = message; + } + + /** Empty constructor */ + public ServerAnswer() { + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + if (status == null || (!status.equals(OK) && !status.equals(ERROR))) + throw new ArgeoServerException("Bad status format: " + status); + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Boolean isOk() { + return status.equals(OK); + } + + public Boolean isError() { + return status.equals(ERROR); + } + + public static ServerAnswer error(String message) { + return new ServerAnswer(ERROR, message); + } + + public static ServerAnswer error(Throwable e) { + StringWriter writer = new StringWriter(); + try { + e.printStackTrace(new PrintWriter(writer)); + return new ServerAnswer(ERROR, writer.toString()); + } finally { + IOUtils.closeQuietly(writer); + } + } + + public static ServerAnswer ok(String message) { + return new ServerAnswer(OK, message); + } + +} diff --git a/server/runtime/org.argeo.server.json/pom.xml b/server/runtime/org.argeo.server.json/pom.xml index 5b7991ba7..182f74d4c 100644 --- a/server/runtime/org.argeo.server.json/pom.xml +++ b/server/runtime/org.argeo.server.json/pom.xml @@ -38,6 +38,13 @@ + + + org.argeo.commons.server + org.argeo.server.core + 0.1.1-SNAPSHOT + + org.codehaus.jackson diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonView.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonView.java index fcd070a4a..2d342e9b3 100644 --- a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonView.java +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonView.java @@ -1,17 +1,25 @@ -package org.argeo.slc.web.mvc; +package org.argeo.server.json.mvc; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.argeo.server.ArgeoServerException; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.ObjectMapper; import org.springframework.web.servlet.view.AbstractView; /** Marshal one of the object of the map to the output. */ public class JsonView extends AbstractView { + private JsonFactory jsonFactory = new JsonFactory(); + private ObjectMapper objectMapper = new ObjectMapper(); + private String modelKey = null; - public JsonView() { + public JsonView(String modelKey) { + this.modelKey = modelKey; } @Override @@ -20,24 +28,26 @@ public class JsonView extends AbstractView { HttpServletRequest request, HttpServletResponse response) throws Exception { final Object answer; - if (modelKey != null) { + if (model.size() == 1) + answer = model.values().iterator().next(); + else if (modelKey != null) { if (!model.containsKey(modelKey)) - throw new SlcException("Key " + modelKey + throw new ArgeoServerException("Key " + modelKey + " not found in model."); answer = model.get(modelKey); - } else { - if (model.size() != 1) - throw new SlcException( - "Model has a size different from 1. Specify a modelKey."); - answer = model.values().iterator().next(); + } else {// models.size!=1 and no modelKey + throw new ArgeoServerException( + "Model has a size different from 1. Specify a modelKey."); } - if (answer instanceof JSONObject) { - ((JSONObject) answer).write(response.getWriter()); - } else { - JSONObject jsonObject = new JSONObject(answer); - jsonObject.write(response.getWriter()); - } + response.setContentType("application/json"); + + JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(response + .getWriter()); + jsonGenerator.useDefaultPrettyPrinter(); + + objectMapper.writeValue(jsonGenerator, answer); + } public void setModelKey(String modelKey) { diff --git a/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonViewResolver.java b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonViewResolver.java new file mode 100644 index 000000000..a3b5e0ddb --- /dev/null +++ b/server/runtime/org.argeo.server.json/src/main/java/org/argeo/server/json/mvc/JsonViewResolver.java @@ -0,0 +1,18 @@ +package org.argeo.server.json.mvc; + +import java.util.Locale; + +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.view.AbstractCachingViewResolver; + +/** + * Returns a {@link JsonView} based on the underlying. View name is the model + * key of the JSON view. + */ +public class JsonViewResolver extends AbstractCachingViewResolver { + @Override + protected View loadView(String viewName, Locale locale) throws Exception { + return new JsonView(viewName); + } + +} diff --git a/server/runtime/pom.xml b/server/runtime/pom.xml index 73717be9d..b38010213 100644 --- a/server/runtime/pom.xml +++ b/server/runtime/pom.xml @@ -13,6 +13,7 @@ Commons Security Runtime pom + org.argeo.server.core org.argeo.server.json \ No newline at end of file -- 2.30.2