splitted database from account
This commit is contained in:
@ -62,6 +62,7 @@
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account</artifactId>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
|
||||
@ -14,13 +14,22 @@
|
||||
|
||||
<name>shared-account</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>10</maven.compiler.source>
|
||||
<maven.compiler.target>10</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-db</artifactId>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-account-dao</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
@ -44,10 +53,6 @@
|
||||
<artifactId>shared-jeeutil</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-account-dao</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@ -68,11 +73,6 @@
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
|
||||
@ -71,7 +71,15 @@ public class AccountProducer implements Serializable {
|
||||
public Account getAccount() {
|
||||
String accountName;
|
||||
if (account == null) {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
Subject subject = null;
|
||||
try {
|
||||
subject = SecurityUtils.getSubject();
|
||||
} catch (Exception ex) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.error("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
}
|
||||
if (subject == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.ControllerException;
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.ApiKeyEntity;
|
||||
@ -24,6 +23,7 @@ import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.dao.ApiKeyObject;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTDecoder;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTEncoder;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTException;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.ControllerException;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.instance.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.ControllerException;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
|
||||
52
db/pom.xml
Normal file
52
db/pom.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-db</artifactId>
|
||||
<packaging>ejb</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>shared</artifactId>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>shared-db</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-web-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- create EJB version 3.1 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-ejb-plugin</artifactId>
|
||||
<configuration>
|
||||
<ejbVersion>3.1</ejbVersion>
|
||||
<excludes>
|
||||
<exclude>**/persistence.xml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -13,11 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
||||
import de.muehlencord.shared.account.util.ApplicationPU;
|
||||
import de.muehlencord.shared.account.util.Updateable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
@ -41,7 +38,7 @@ import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.shiro.util.StringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -54,9 +51,6 @@ public abstract class AbstractController<T> {
|
||||
@ApplicationPU
|
||||
protected EntityManager em;
|
||||
|
||||
@Inject
|
||||
protected Account account;
|
||||
|
||||
private final Class<T> entityClass;
|
||||
|
||||
public AbstractController(Class<T> clazz) {
|
||||
@ -187,12 +181,12 @@ public abstract class AbstractController<T> {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void applyUpdateableChanges(Updateable updateable, boolean onCreate) throws ControllerException {
|
||||
public void applyUpdateableChanges(Updateable updateable, boolean onCreate, String updatedBy) throws ControllerException {
|
||||
if (onCreate) {
|
||||
updateable.setCreatedBy(account.getUsername());
|
||||
updateable.setCreatedBy(updatedBy);
|
||||
updateable.setCreatedOn(new Date());
|
||||
}
|
||||
updateable.setLastUpdatedBy(account.getUsername());
|
||||
updateable.setLastUpdatedBy(updatedBy);
|
||||
updateable.setLastUpdatedOn(new Date());
|
||||
}
|
||||
|
||||
@ -203,10 +197,10 @@ public abstract class AbstractController<T> {
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T create(T entity) throws ControllerException {
|
||||
public T create(T entity, String createdBy) throws ControllerException {
|
||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
||||
Updateable updateable = (Updateable) entity;
|
||||
applyUpdateableChanges(updateable, true);
|
||||
applyUpdateableChanges(updateable, true, createdBy);
|
||||
}
|
||||
em.persist(entity);
|
||||
return entity;
|
||||
@ -215,10 +209,10 @@ public abstract class AbstractController<T> {
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T update(T entity) throws ControllerException {
|
||||
public T update(T entity, String updatedBy) throws ControllerException {
|
||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
||||
Updateable updateable = (Updateable) entity;
|
||||
applyUpdateableChanges(updateable, false);
|
||||
applyUpdateableChanges(updateable, false, updatedBy);
|
||||
}
|
||||
return em.merge(entity);
|
||||
}
|
||||
@ -226,7 +220,7 @@ public abstract class AbstractController<T> {
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public void delete(T entity) throws ControllerException {
|
||||
public void delete(T entity, String deletedBy) throws ControllerException {
|
||||
em.remove(attach(entity));
|
||||
}
|
||||
|
||||
@ -13,10 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import de.muehlencord.shared.account.util.EndDateable;
|
||||
import de.muehlencord.shared.account.util.Updateable;
|
||||
import de.muehlencord.shared.util.DateUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -51,11 +49,11 @@ public abstract class AbstractEnddateableController<T extends EndDateable<T>> ex
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@Override
|
||||
public void delete(T entity) throws ControllerException {
|
||||
public void delete(T entity, String deletedBy) throws ControllerException {
|
||||
T entityToUpdate = attach(entity);
|
||||
if (Updateable.class.isAssignableFrom(entityToUpdate.getClass())) {
|
||||
Updateable updateable = (Updateable) entityToUpdate;
|
||||
applyUpdateableChanges(updateable, false);
|
||||
applyUpdateableChanges(updateable, false, deletedBy);
|
||||
}
|
||||
entityToUpdate.setValidTo(DateUtil.getCurrentTimeInUTC());
|
||||
em.merge(entityToUpdate);
|
||||
@ -65,19 +63,19 @@ public abstract class AbstractEnddateableController<T extends EndDateable<T>> ex
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T create(T entity) throws ControllerException {
|
||||
public T create(T entity, String createdBy) throws ControllerException {
|
||||
entity.setValidFrom(DateUtil.getCurrentTimeInUTC());
|
||||
return super.create(entity);
|
||||
return super.create(entity, createdBy);
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@Override
|
||||
public T update(T entity) throws ControllerException {
|
||||
public T update(T entity, String createdBy) throws ControllerException {
|
||||
T newEntity = entity.cloneEndDateable();
|
||||
delete(entity);
|
||||
return create (newEntity);
|
||||
delete(entity, createdBy);
|
||||
return create(newEntity, createdBy);
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@ -92,7 +90,7 @@ public abstract class AbstractEnddateableController<T extends EndDateable<T>> ex
|
||||
|
||||
Predicate validToNotSet = cb.isNull(root.get("validTo"));
|
||||
Predicate isBeforeValidTo = cb.greaterThanOrEqualTo(root.get("validTo"), now);
|
||||
Predicate stillValid = cb.or (isBeforeValidTo, validToNotSet);
|
||||
Predicate stillValid = cb.or(isBeforeValidTo, validToNotSet);
|
||||
Predicate isValid = cb.and(alreadyValid, stillValid);
|
||||
criteria.where(isValid);
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.muehlencord.shared.account.util;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
@ -1,4 +1,4 @@
|
||||
package de.muehlencord.shared.account.util;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import javax.annotation.Priority;
|
||||
import javax.inject.Inject;
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import javax.ejb.ApplicationException;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.muehlencord.shared.account.util;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package de.muehlencord.shared.account.util;
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -45,6 +45,10 @@ public class APIException extends RuntimeException {
|
||||
httpResponse = createHttpResponse(new APIErrorResponse(apiError, locale, rootCause));
|
||||
}
|
||||
|
||||
public APIException(APIError apiError, String locale, String rootCause) {
|
||||
httpResponse = createHttpResponse(new APIErrorResponse(apiError, new Locale(locale), rootCause));
|
||||
}
|
||||
|
||||
public APIException(Exception exception, Locale locale) {
|
||||
httpResponse = createHttpResponse(new APIErrorResponse(exception, locale));
|
||||
}
|
||||
|
||||
18
pom.xml
18
pom.xml
@ -19,6 +19,7 @@
|
||||
<module>poi-util</module>
|
||||
<module>account-ui</module>
|
||||
<module>account-dao</module>
|
||||
<module>db</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
@ -35,6 +36,18 @@
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-db</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account-dao</artifactId>
|
||||
@ -45,11 +58,6 @@
|
||||
<artifactId>shared-shiro-faces</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-sharepoint</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>de.muehlencord.shared.sharepoint</groupId>
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
<parent>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
<artifactId>shared</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-sharepoint</artifactId>
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-shiro-faces</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>shared-shiro-faces</name>
|
||||
|
||||
<parent>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
@ -12,6 +11,7 @@
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>shared-shiro-faces</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@ -2,6 +2,8 @@ package de.muehlencord.shared.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -11,7 +13,9 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public abstract class StringUtil {
|
||||
|
||||
/** the logging object */
|
||||
/**
|
||||
* the logging object
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StringUtil.class);
|
||||
|
||||
/**
|
||||
@ -27,7 +31,7 @@ public abstract class StringUtil {
|
||||
byte[] b = input.getBytes("UTF-8");
|
||||
return new String(b, "ISO-8859-1");
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
LOGGER.debug (ex.toString(), ex);
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
throw new StringEncodingException("Cannot convert string from UTF-8 to ISO-8859-1. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
@ -40,13 +44,13 @@ public abstract class StringUtil {
|
||||
*/
|
||||
public static String getStackTraceString(Throwable ex) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append (ex.toString());
|
||||
sb.append ("\n");
|
||||
sb.append(ex.toString());
|
||||
sb.append("\n");
|
||||
|
||||
StackTraceElement[] stack = ex.getStackTrace();
|
||||
for (StackTraceElement currentElement : stack) {
|
||||
sb.append (currentElement.toString());
|
||||
sb.append ("\n");
|
||||
sb.append(currentElement.toString());
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@ -56,7 +60,7 @@ public abstract class StringUtil {
|
||||
*
|
||||
*
|
||||
*
|
||||
|
||||
*
|
||||
*
|
||||
* @param length the needed length for this field
|
||||
* @param s the field to extend with blanks
|
||||
@ -68,42 +72,45 @@ public abstract class StringUtil {
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append (s);
|
||||
sb.append(s);
|
||||
while (sb.toString().length() < length) {
|
||||
sb.append (" ");
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the string located between the two given keywords
|
||||
*
|
||||
* @param content the string to get the value from
|
||||
* @param keyWord1 the starting keyword
|
||||
* @param keyWord2 the end keywod
|
||||
* @return the string between keyword1 and keyword2
|
||||
* @throws ParseException if the value cannot be determined - e.g. if one of the keywords is not found
|
||||
* @throws ParseException if the value cannot be determined - e.g. if one of
|
||||
* the keywords is not found
|
||||
*/
|
||||
public static String getValueBetweenKeywords(String content, String keyWord1, String keyWord2) throws ParseException {
|
||||
int pos1 = content.indexOf(keyWord1);
|
||||
if (pos1 == -1) {
|
||||
throw new ParseException("Keyword1=" + keyWord1 + " not found in content string",0);
|
||||
throw new ParseException("Keyword1=" + keyWord1 + " not found in content string", 0);
|
||||
}
|
||||
|
||||
int pos2 = content.indexOf(keyWord2, pos1);
|
||||
if (pos2 == -1) {
|
||||
throw new ParseException("Keyword2=" + keyWord2 + " not found in content string",0);
|
||||
throw new ParseException("Keyword2=" + keyWord2 + " not found in content string", 0);
|
||||
}
|
||||
String returnValue = content.substring(pos1+keyWord1.length(), pos2);
|
||||
String returnValue = content.substring(pos1 + keyWord1.length(), pos2);
|
||||
returnValue = returnValue.trim();
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true, if given string is either null or a blank string
|
||||
*
|
||||
* @param s the string to check
|
||||
* @return true, if s is either null or s.equals("")
|
||||
*/
|
||||
public static boolean isEmpty(String s) {
|
||||
return (s == null) || (s.equals (""));
|
||||
return (s == null) || (s.equals(""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user