Merge branch 'develop'

This commit is contained in:
Paulo Gustavo Veiga 2022-03-27 14:56:51 -03:00
commit ef43e2889e
143 changed files with 1128 additions and 2464 deletions

View File

@ -46,7 +46,7 @@ In order to reduce the life-cycle to develop UI backend testing, you can do the
A quick and dirty solution to share changes in the UI is to manually compile the dist. This will make the loader file available without the need to publish:
`cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist`
`yarn --cwd wisemapping-frontend build;cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist;cp -r wisemapping-frontend/packages/mindplot/dist/* wisemapping-open-source/wise-ui/target/wisemapping-mindplot/package/dist`
### Compiling and running with docker-compose

View File

@ -4,7 +4,7 @@
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<com.wisemapping.version>5.0.9</com.wisemapping.version>
<com.wisemapping.version>5.0.10-SNAPSHOT</com.wisemapping.version>
<superpom.dir>${project.basedir}/wise-webapps</superpom.dir>
</properties>
@ -16,7 +16,7 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<name>WiseMapping Project</name>
<version>5.0.9</version>
<version>5.0.10-SNAPSHOT</version>
<packaging>pom</packaging>
<licenses>

View File

@ -12,7 +12,7 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<relativePath>../pom.xml</relativePath>
<version>5.0.9</version>
<version>5.0.10-SNAPSHOT</version>
</parent>
<build>

View File

@ -9,7 +9,7 @@
<groupId>org.wisemapping</groupId>
<artifactId>wisemapping</artifactId>
<relativePath>../pom.xml</relativePath>
<version>5.0.9</version>
<version>5.0.10-SNAPSHOT</version>
</parent>
<properties>

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,33 +1,37 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import com.wisemapping.model.Collaborator;
import com.wisemapping.model.User;
import org.jetbrains.annotations.NotNull;
public class AccessDeniedSecurityException
extends ClientException
{
extends ClientException {
public static final String MSG_KEY = "ACCESS_HAS_BEEN_REVOKED";
public AccessDeniedSecurityException(@NotNull String msg)
{
super(msg,Severity.FATAL);
public AccessDeniedSecurityException(@NotNull String msg) {
super(msg, Severity.FATAL);
}
public AccessDeniedSecurityException(@NotNull long mapId, Collaborator user) {
super("No enough permissions to access map. Id: " + mapId + ", User: " + user, Severity.FATAL);
}
@NotNull

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import org.jetbrains.annotations.NotNull;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -0,0 +1,39 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import org.springframework.lang.Nullable;
import javax.validation.constraints.NotNull;
public class InvalidEmailException
extends ClientException {
private static final String EMAIL_IS_INVALID = "INVALID_EMAIL_ADDRESS";
public InvalidEmailException(@NotNull String emails) {
super("Invalid email exception:" + emails, Severity.WARNING);
}
@NotNull
@Override
protected String getMsgBundleKey() {
return EMAIL_IS_INVALID;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import org.jetbrains.annotations.NotNull;

View File

@ -1,32 +1,39 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.exceptions;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import com.wisemapping.service.LockManager;
import org.jetbrains.annotations.NotNull;
public class LockException
extends ClientException
{
extends ClientException {
private static final String MSG_KEY = "MINDMAP_IS_LOCKED";
public LockException(@NotNull String message) {
super(message,Severity.INFO);
super(message, Severity.INFO);
}
public static LockException createLockLost(@NotNull Mindmap mindmap, @NotNull User user, @NotNull LockManager manager) {
return new LockException("Lock can not be granted to " + user.getEmail() + ". The lock is assigned to " + manager.getLockInfo(mindmap));
}
@NotNull

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -48,7 +48,7 @@ public class RequestPropertiesInterceptor implements HandlerInterceptor {
@Value("${site.homepage}")
private String siteHomepage;
@Value("${site.baseurl}")
@Value("${site.baseurl:http://localhost:8080}")
private String siteUrl;
@Value("${security.type}")

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.listener;
@ -7,6 +24,7 @@ import com.wisemapping.model.User;
import com.wisemapping.security.Utils;
import com.wisemapping.service.LockManager;
import com.wisemapping.service.MindmapService;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
@ -16,6 +34,7 @@ import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class UnlockOnExpireListener implements HttpSessionListener {
private static final Logger logger = Logger.getLogger(UnlockOnExpireListener.class);
@Override
public void sessionCreated(@NotNull HttpSessionEvent event) {
@ -28,16 +47,16 @@ public class UnlockOnExpireListener implements HttpSessionListener {
final ServletContext servletContext = event.getSession().getServletContext();
final WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
final MindmapService mindmapService = (MindmapService) wc.getBean("mindmapService");
final LockManager lockManager = mindmapService.getLockManager();
final LockManager lockManager = mindmapService.getLockManager();
final User user = Utils.getUser(false);
if (user != null) {
try {
lockManager.unlockAll(user);
} catch (LockException e) {
e.printStackTrace();
} catch (AccessDeniedSecurityException e) {
e.printStackTrace();
synchronized (mindmapService.getLockManager()) {
try {
lockManager.unlockAll(user);
} catch (LockException | AccessDeniedSecurityException e) {
logger.error(e);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -23,38 +23,35 @@ import com.wisemapping.model.Collaboration;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import com.wisemapping.rest.model.RestLogItem;
import com.wisemapping.util.VelocityEngineUtils;
import com.wisemapping.util.VelocityEngineWrapper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ResourceBundleMessageSource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
final public class NotificationService {
final private static Logger logger = Logger.getLogger(Mailer.class);
final private static String DEFAULT_WISE_URL = "http://localhost:8080/wisemapping";
private VelocityEngineWrapper velocityEngineWrapper;
private ResourceBundleMessageSource messageSource;
@Autowired
private Mailer mailer;
private String baseUrl;
public NotificationService() {
NotifierFilter notificationFilter = new NotifierFilter();
}
public void newCollaboration(@NotNull Collaboration collaboration, @NotNull Mindmap mindmap, @NotNull User user, @Nullable String message) {
final Locale locale = LocaleContextHolder.getLocale();
try {
// Sent collaboration email ...
@ -64,12 +61,11 @@ final public class NotificationService {
final String collabEmail = collaboration.getCollaborator().getEmail();
// Build the subject ...
final String subject = "[WiseMapping] " + user.getFullName() + " has shared a mindmap with you";
final String subject = messageSource.getMessage("SHARE_MAP.EMAIL_SUBJECT", new Object[]{user.getFullName()}, locale);
// Fill template properties ...
final Map<String, Object> model = new HashMap<>();
model.put("mindmap", mindmap);
model.put("message", "message");
model.put("ownerName", user.getFirstname());
model.put("mapEditUrl", getBaseUrl() + "/c/maps/" + mindmap.getId() + "/edit");
model.put("baseUrl", getBaseUrl());
@ -85,31 +81,32 @@ final public class NotificationService {
}
public void resetPassword(@NotNull User user, @NotNull String temporalPassword) {
final String mailSubject = "[WiseMapping] Your new password";
final String messageTitle = "Your new password has been generated";
final String messageBody =
"<p>Someone, most likely you, requested a new password for your WiseMapping account. </p>\n" +
"<p><strong>Here is your new password: " + temporalPassword + "</strong></p>\n" +
"<p>You can login clicking <a href=\"" + getBaseUrl() + "/c/login\">here</a>. We strongly encourage you to change the password as soon as possible.</p>";
final Locale locale = LocaleContextHolder.getLocale();
final String mailSubject = messageSource.getMessage("CHANGE_PASSWORD.EMAIL_SUBJECT", null, locale);
final String messageTitle = messageSource.getMessage("CHANGE_PASSWORD.EMAIL_TITLE", null, locale);
final String messageBody = messageSource.getMessage("CHANGE_PASSWORD.EMAIL_BODY", new Object[]{temporalPassword, getBaseUrl()}, locale);
sendTemplateMail(user, mailSubject, messageTitle, messageBody);
}
public void passwordChanged(@NotNull User user) {
final String mailSubject = "[WiseMapping] Your password has been changed";
final String messageTitle = "Your password has been changed successfully";
final String messageBody =
"<p>This is only an notification that your password has been changed. No further action is required.</p>";
final Locale locale = LocaleContextHolder.getLocale();
final String mailSubject = messageSource.getMessage("PASSWORD_CHANGED.EMAIL_SUBJECT", null, locale);
final String messageTitle = messageSource.getMessage("PASSWORD_CHANGED.EMAIL_TITLE", null, locale);
final String messageBody = messageSource.getMessage("PASSWORD_CHANGED.EMAIL_BODY", null, locale);
sendTemplateMail(user, mailSubject, messageTitle, messageBody);
}
public void newAccountCreated(@NotNull User user) {
final String mailSubject = "Welcome to WiseMapping !";
final String messageTitle = "Your account has been created successfully";
final String messageBody =
"<p> Thank you for your interest in WiseMapping. Click <a href='https://app.wisemapping.com/c/login'>here</a> to start creating and sharing new mind maps. If have any feedback or idea, send us an email to <a href=\"mailto:feedback@wisemapping.com\">feedback@wisemapping.com</a> .We'd love to hear from you.</p>";
final Locale locale = LocaleContextHolder.getLocale();
final String mailSubject = messageSource.getMessage("REGISTRATION.EMAIL_SUBJECT", null, locale);
final String messageTitle = messageSource.getMessage("REGISTRATION.EMAIL_TITLE", null, locale);
final String messageBody = messageSource.getMessage("REGISTRATION.EMAIL_BODY", null, locale);
sendTemplateMail(user, mailSubject, messageTitle, messageBody);
}
@ -123,6 +120,7 @@ final public class NotificationService {
model.put("baseUrl", getBaseUrl());
model.put("supportEmail", mailer.getSupportEmail());
logger.debug("Email properties->" + model);
mailer.sendEmail(mailer.getServerSenderEmail(), user.getEmail(), mailSubject, model, "baseLayout.vm");
} catch (Exception e) {
handleException(e);
@ -160,10 +158,6 @@ final public class NotificationService {
// }
}
public void setVelocityEngineWrapper(VelocityEngineWrapper engine) {
this.velocityEngineWrapper = engine;
}
public void reportJavascriptException(@Nullable Mindmap mindmap, @Nullable User user, @NotNull RestLogItem errorItem, @NotNull HttpServletRequest request) {
final Map<String, String> summary = new HashMap<>();
@ -210,32 +204,30 @@ final public class NotificationService {
}
public String stackTraceToString(@NotNull Throwable e) {
String retValue;
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw);
String retValue = "";
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
try (sw; pw) {
e.printStackTrace(pw);
retValue = sw.toString();
} finally {
IOUtils.closeQuietly(pw);
IOUtils.closeQuietly(sw);
} catch (IOException ioException) {
ioException.printStackTrace();
}
return retValue;
}
public String getBaseUrl() {
if ("${site.baseurl}".equals(baseUrl)) {
baseUrl = DEFAULT_WISE_URL;
System.err.println("Warning: site.baseurl has not being configured. Mail site references could be not properly sent. Using :" + baseUrl);
}
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void setMessageSource(ResourceBundleMessageSource messageSource) {
this.messageSource = messageSource;
}
}

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.mail;
import org.jetbrains.annotations.NotNull;

View File

@ -1,43 +0,0 @@
package com.wisemapping.mail;
import com.wisemapping.model.User;
import com.wisemapping.security.Utils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.Set;
public class NotifyingExceptionResolver extends SimpleMappingExceptionResolver {
final private Logger logger = Logger.getLogger(NotifyingExceptionResolver.class);
private Set<String> exclude = new HashSet<String>();
private NotificationService notificationService;
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (!exclude.contains(ex.getClass().getName())) {
logger.error("An Exception has occurred in the application", ex);
sendNotification(ex, request);
}
return super.doResolveException(request, response, handler, ex);
}
private void sendNotification(@NotNull Exception ex, @NotNull HttpServletRequest request) {
final User user = Utils.getUser(false);
notificationService.reportJavaException(ex, user, request);
}
public void setExclude(final Set<String> exclude) {
this.exclude = exclude;
}
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.model;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.model;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.model;
@ -19,10 +36,16 @@ abstract public class MindmapUtils {
throw InvalidMindmapException.invalidFormat(xmlDoc);
}
// Validate that the number of nodes is not bigger 500 nodes.
int numberOfTopics = xmlDoc.split("<topic").length;
// Any valid map must contain at least a central topic ...
if (numberOfTopics == 0) {
throw InvalidMindmapException.invalidFormat(xmlDoc);
}
// Validate that the number of nodes is not bigger 5000 nodes.
if (numberOfTopics > MAX_SUPPORTED_NODES) {
throw InvalidMindmapException.tooBigMindnap(numberOfTopics);
}
}
}

View File

@ -1,20 +1,20 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.model;
@ -29,7 +29,7 @@ import java.util.Set;
@Entity
@Table(name = "USER")
@PrimaryKeyJoinColumn(name="colaborator_id")
@PrimaryKeyJoinColumn(name = "colaborator_id")
public class User
extends Collaborator
implements Serializable {
@ -48,10 +48,10 @@ public class User
@Column(name = "allow_send_email")
private boolean allowSendEmail = false;
@Column(name="authentication_type")
@Column(name = "authentication_type")
private Character authenticationTypeCode = AuthenticationType.DATABASE.getCode();
@Column(name="authenticator_uri")
@Column(name = "authenticator_uri")
private String authenticatorUri;
@ElementCollection
@ -93,6 +93,7 @@ public class User
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@ -143,14 +144,14 @@ public class User
}
public AuthenticationType getAuthenticationType() {
return authenticationTypeCode!=null ? AuthenticationType.valueOf(authenticationTypeCode):AuthenticationType.DATABASE;
return authenticationTypeCode != null ? AuthenticationType.valueOf(authenticationTypeCode) : AuthenticationType.DATABASE;
}
public void setAuthenticationType(@NotNull AuthenticationType authenticationType) {
this.authenticationTypeCode = authenticationType.getCode();
}
public boolean isDatabaseSchema(){
public boolean isDatabaseSchema() {
return this.getAuthenticationType() == AuthenticationType.DATABASE;
}
@ -162,5 +163,11 @@ public class User
this.authenticatorUri = authenticatorUri;
}
@Override
public String toString() {
return "User{" +
"firstname='" + firstname + '\'' +
", lastname='" + lastname + '\'' +
"', email = '" + this.getEmail() + "}";
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -124,15 +124,4 @@ public class AccountController extends BaseController {
}
userService.removeUser(user);
}
@RequestMapping(method = RequestMethod.POST, value = "/logger/editor", consumes = {"application/xml", "application/json"}, produces = {"application/json", "text/html", "application/xml"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void logError(@RequestBody RestLogItem item, @NotNull HttpServletRequest request) {
final Mindmap mindmap = mindmapService.findMindmapById(item.getMapId());
final User user = Utils.getUser();
notificationService.reportJavascriptException(mindmap, user, item, request);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -138,17 +138,4 @@ public class AdminController extends BaseController {
userService.removeUser(user);
}
private boolean isWelcomeMap(@NotNull Mindmap mindmap) throws UnsupportedEncodingException {
// Is welcome map ?
final String xmlStr = mindmap.getXmlStr();
boolean oldWelcomeMap = xmlStr.contains("Welcome to WiseMapping") && xmlStr.contains("My Wisemaps");
return oldWelcomeMap;
}
public boolean isSimpleMap(@NotNull Mindmap mindmap) throws UnsupportedEncodingException {
String xmlStr = mindmap.getXmlStr();
String[] topics = xmlStr.split(Pattern.quote("<topic"));
return topics.length <= 3;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2011] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -15,7 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.rest;
import com.wisemapping.exceptions.ClientException;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.rest;
import com.wisemapping.exceptions.LabelCouldNotFoundException;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -18,10 +18,7 @@
package com.wisemapping.rest;
import com.wisemapping.exceptions.LabelCouldNotFoundException;
import com.wisemapping.exceptions.MapCouldNotFoundException;
import com.wisemapping.exceptions.SessionExpiredException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.exceptions.*;
import com.wisemapping.model.*;
import com.wisemapping.rest.model.*;
import com.wisemapping.security.Utils;
@ -33,6 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
@ -43,6 +41,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Controller
@ -111,8 +110,8 @@ public class MindmapController extends BaseController {
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/document", consumes = {"application/xml", "application/json"}, produces = {"application/json", "application/xml"})
@ResponseBody
public Long updateDocument(@RequestBody RestMindmap restMindmap, @PathVariable int id, @RequestParam(required = false) boolean minor, @RequestParam(required = false) Long timestamp, @RequestParam(required = false) Long session) throws WiseMappingException, IOException {
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateDocument(@RequestBody RestMindmap restMindmap, @PathVariable int id, @RequestParam(required = false) boolean minor) throws WiseMappingException, IOException {
final Mindmap mindmap = findMindmapById(id);
final User user = Utils.getUser();
@ -123,10 +122,9 @@ public class MindmapController extends BaseController {
throw new IllegalArgumentException("Map properties can not be null");
}
// Could the map be updated ?
if (session != null) {
verifyLock(mindmap, user, session, timestamp);
}
// Have permissions ?
final LockManager lockManager = mindmapService.getLockManager();
lockManager.lock(mindmap, user);
// Update collaboration properties ...
final CollaborationProperties collaborationProperties = mindmap.findCollaborationProperties(user);
@ -138,15 +136,6 @@ public class MindmapController extends BaseController {
// Update map ...
saveMindmapDocument(minor, mindmap, user);
// Update edition timeout ...
final LockManager lockManager = mindmapService.getLockManager();
long result = -1;
if (session != null) {
final LockInfo lockInfo = lockManager.updateExpirationTimeout(mindmap, user);
result = lockInfo.getTimestamp();
}
return result;
}
@RequestMapping(method = RequestMethod.GET, value = {"/maps/{id}/document/xml", "/maps/{id}/document/xml-pub"}, consumes = {"text/plain"}, produces = {"application/xml; charset=UTF-8"})
@ -176,36 +165,6 @@ public class MindmapController extends BaseController {
return mindmapHistory.getUnzipXml();
}
private void verifyLock(@NotNull Mindmap mindmap, @NotNull User user, long session, long timestamp) throws WiseMappingException {
// The lock was lost, reclaim as the ownership of it.
final LockManager lockManager = mindmapService.getLockManager();
final boolean lockLost = lockManager.isLocked(mindmap);
if (!lockLost) {
lockManager.lock(mindmap, user, session);
}
final LockInfo lockInfo = lockManager.getLockInfo(mindmap);
if (lockInfo.getUser().identityEquality(user)) {
long savedTimestamp = mindmap.getLastModificationTime().getTimeInMillis();
final boolean outdated = savedTimestamp > timestamp;
if (lockInfo.getSession() == session) {
// Timestamp might not be returned to the client. This try to cover this case, ignoring the client timestamp check.
final User lastEditor = mindmap.getLastEditor();
boolean editedBySameUser = lastEditor == null || user.identityEquality(lastEditor);
if (outdated && !editedBySameUser) {
throw new SessionExpiredException("Map has been updated by " + (lastEditor.getEmail()) + ",Timestamp:" + timestamp + "," + savedTimestamp + ", User:" + lastEditor.getId() + ":" + user.getId() + ",Mail:'" + lastEditor.getEmail() + "':'" + user.getEmail(), lastEditor);
}
} else if (outdated) {
logger.warn("Sessions:" + session + ":" + lockInfo.getSession() + ",Timestamp: " + timestamp + ": " + savedTimestamp);
// @Todo: Temporally disabled to unblock save action. More research needed.
// throw new MultipleSessionsOpenException("Sessions:" + session + ":" + lockInfo.getSession() + ",Timestamp: " + timestamp + ": " + savedTimestamp);
}
} else {
throw new SessionExpiredException("Different Users.", lockInfo.getUser());
}
}
/**
* The intention of this method is the update of several properties at once ...
@ -249,8 +208,15 @@ public class MindmapController extends BaseController {
}
@NotNull
private Mindmap findMindmapById(int id) throws MapCouldNotFoundException {
Mindmap result = mindmapService.findMindmapById(id);
private Mindmap findMindmapById(int id) throws MapCouldNotFoundException, AccessDeniedSecurityException {
// Has enough permissions ?
final User user = Utils.getUser();
if (!mindmapService.hasPermissions(user, id, CollaborationRole.VIEWER)) {
throw new AccessDeniedSecurityException(id, user);
}
// Does the map exists ?
final Mindmap result = mindmapService.findMindmapById(id);
if (result == null) {
throw new MapCouldNotFoundException("Map could not be found. Id:" + id);
}
@ -277,7 +243,7 @@ public class MindmapController extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = "/maps/{id}/collabs/", consumes = {"application/json", "application/xml"}, produces = {"application/json", "application/xml"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateCollabs(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException {
public void updateCollabs(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException {
final Mindmap mindMap = findMindmapById(id);
// Only owner can change collaborators...
@ -293,7 +259,7 @@ public class MindmapController extends BaseController {
// Is a valid email address ?
if (!EmailValidator.getInstance().isValid(email)) {
throw new IllegalArgumentException(email + " is not valid email address");
throw new InvalidEmailException(email);
}
final Collaboration collaboration = mindMap.findCollaboration(email);
@ -303,7 +269,7 @@ public class MindmapController extends BaseController {
throw new IllegalArgumentException(roleStr + " is not a valid role");
}
// Remove from the list of pendings to remove ...
// Remove from the list of pending to remove ...
if (collaboration != null) {
collabsToRemove.remove(collaboration);
}
@ -324,25 +290,26 @@ public class MindmapController extends BaseController {
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/collabs/", consumes = {"application/json", "application/xml"}, produces = {"application/json", "application/xml"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void addCollab(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException {
public void addCollab(@PathVariable int id, @NotNull @RequestBody RestCollaborationList restCollabs) throws CollaborationException, MapCouldNotFoundException, AccessDeniedSecurityException, InvalidEmailException {
final Mindmap mindMap = findMindmapById(id);
// Only owner can change collaborators...
final User user = Utils.getUser();
if (!mindMap.hasPermissions(user, CollaborationRole.OWNER)) {
throw new IllegalArgumentException("No enough permissions");
throw new AccessDeniedSecurityException("User must be owner to share mindmap");
}
// Is valid email address ?
final EmailValidator emailValidator = EmailValidator.getInstance();
restCollabs
final Set<String> invalidEmails = restCollabs
.getCollaborations()
.forEach(collab -> {
// Is a valid email address ?
if (!emailValidator.isValid(collab.getEmail())) {
throw new IllegalArgumentException(collab.getEmail() + " is not valid email address");
}
});
.stream()
.map(RestCollaboration::getEmail)
.filter(e -> !emailValidator.isValid(e)).collect(Collectors.toSet());
if (!invalidEmails.isEmpty()) {
throw new InvalidEmailException(String.join(", ", invalidEmails));
}
// Has any role changed ?. Just removed it.
final Map<String, Collaboration> mapsByEmail = mindMap
@ -385,7 +352,7 @@ public class MindmapController extends BaseController {
@RequestMapping(method = RequestMethod.GET, value = "/maps/{id}/collabs", produces = {"application/json", "application/xml"})
public RestCollaborationList retrieveList(@PathVariable int id) throws MapCouldNotFoundException {
public RestCollaborationList retrieveList(@PathVariable int id) throws MapCouldNotFoundException, AccessDeniedSecurityException {
final Mindmap mindMap = findMindmapById(id);
final Set<Collaboration> collaborations = mindMap.getCollaborations();
@ -403,14 +370,9 @@ public class MindmapController extends BaseController {
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/description", consumes = {"text/plain"}, produces = {"application/json", "application/xml"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateDescription(@RequestBody String description, @PathVariable int id) throws WiseMappingException {
final Mindmap mindMap = findMindmapById(id);
final User user = Utils.getUser();
// Update map ...
final Mindmap mindmap = findMindmapById(id);
mindmap.setDescription(description);
mindmapService.updateMindmap(mindMap, false);
mindmapService.updateMindmap(mindmap, false);
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/publish", consumes = {"text/plain"}, produces = {"application/json", "application/xml"})
@ -446,7 +408,7 @@ public class MindmapController extends BaseController {
// Is a valid email address ?
final EmailValidator emailValidator = EmailValidator.getInstance();
if (!emailValidator.isValid(email)) {
throw new IllegalArgumentException(email + " is not valid email address");
throw new InvalidEmailException(email);
}
final Mindmap mindmap = findMindmapById(id);
@ -487,21 +449,6 @@ public class MindmapController extends BaseController {
mindmapService.updateCollaboration(user, collaboration.get());
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/lock", consumes = {"text/plain"}, produces = {"application/json", "application/xml"})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void updateMapLock(@RequestBody String value, @PathVariable int id) throws IOException, WiseMappingException {
final User user = Utils.getUser();
final LockManager lockManager = mindmapService.getLockManager();
final Mindmap mindmap = findMindmapById(id);
final boolean lock = Boolean.parseBoolean(value);
if (!lock) {
lockManager.unlock(mindmap, user);
} else {
throw new UnsupportedOperationException("REST lock must be implemented.");
}
}
@RequestMapping(method = RequestMethod.DELETE, value = "/maps/batch")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void batchDelete(@RequestParam() String ids) throws IOException, WiseMappingException {
@ -618,4 +565,21 @@ public class MindmapController extends BaseController {
mindmap.addLabel(label);
mindmapService.updateMindmap(mindmap, false);
}
@RequestMapping(method = RequestMethod.PUT, value = "/maps/{id}/lock", consumes = {"text/plain"}, produces = {"application/json", "application/xml"})
public ResponseEntity<RestLockInfo> lockMindmap(@RequestBody String value, @PathVariable int id) throws WiseMappingException {
final User user = Utils.getUser();
final LockManager lockManager = mindmapService.getLockManager();
final Mindmap mindmap = findMindmapById(id);
ResponseEntity<RestLockInfo> result = new ResponseEntity<>(null, HttpStatus.NO_CONTENT);
if (Boolean.parseBoolean(value)) {
final LockInfo lockInfo = lockManager.lock(mindmap, user);
final RestLockInfo restLockInfo = new RestLockInfo(lockInfo, user);
result = new ResponseEntity<>(restLockInfo, HttpStatus.OK);
} else {
lockManager.unlock(mindmap, user);
}
return result;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,20 +1,20 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.rest;
@ -23,11 +23,11 @@ import com.wisemapping.exceptions.WiseMappingException;
import org.jetbrains.annotations.NotNull;
import org.springframework.validation.Errors;
public class ValidationException extends WiseMappingException{
public class ValidationException extends WiseMappingException {
private final Errors errors;
public ValidationException(@NotNull Errors errors) {
super("Validation Exceptions:"+errors);
super("Validation Exceptions:" + errors);
this.errors = errors;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,20 +1,20 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.rest.model;
@ -22,6 +22,7 @@ package com.wisemapping.rest.model;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.wisemapping.model.Collaborator;
import com.wisemapping.model.User;
import com.wisemapping.service.LockInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -39,48 +40,24 @@ import javax.xml.bind.annotation.XmlRootElement;
@JsonIgnoreProperties(ignoreUnknown = true)
public class RestLockInfo {
@NotNull
final private Collaborator user;
@Nullable
final private LockInfo lockInfo;
private String email;
// This is required only for compliance with the JAXB serializer.
public RestLockInfo(){
public RestLockInfo() {
this.lockInfo = null;
//noinspection ConstantConditions
this.user = null;
}
public RestLockInfo(@Nullable LockInfo lockInfo, @NotNull Collaborator collaborator) {
this.lockInfo = lockInfo;
this.user = collaborator;
public RestLockInfo(@Nullable LockInfo lockInfo, @NotNull User user) {
this.email = user.getEmail();
}
public boolean isLocked() {
return lockInfo != null;
public String getEmail() {
return email;
}
public void setLocked(boolean locked) {
// Ignore ...
public void setEmail(String email) {
this.email = email;
}
public boolean isLockedByMe() {
return isLocked() && lockInfo != null && lockInfo.getUser().identityEquality(user);
}
public void setLockedByMe(boolean lockedForMe) {
// Ignore ...
}
public long getTimestamp() {
return lockInfo != null ? lockInfo.getTimestamp() : -1;
}
public void setTimestamp(long value) {
//
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/**
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.security;
import org.springframework.security.core.Authentication;

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.security;
import org.springframework.security.web.util.matcher.RequestMatcher;

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.security;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -23,7 +23,6 @@ import javax.servlet.ServletContextListener;
public class HibernateAppListener implements ServletContextListener {
/* Application Startup Event */
public void contextInitialized(ServletContextEvent ce) {
try {

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import com.wisemapping.exceptions.WiseMappingException;

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import com.wisemapping.dao.LabelManager;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
@ -27,16 +27,22 @@ import java.util.Calendar;
public class LockInfo {
final private User user;
private Calendar timeout;
private long session;
private static final int EXPIRATION_MIN = 30;
private long timestamp = -1;
private long previousTimestamp;
public LockInfo(@NotNull User user, @NotNull Mindmap mindmap, long session) {
public int getMapId() {
return mapId;
}
public void setMapId(int mapId) {
this.mapId = mapId;
}
private int mapId;
public LockInfo(@NotNull User user, @NotNull Mindmap mindmap) {
this.user = user;
this.mapId = mindmap.getId();
this.updateTimeout();
this.updateTimestamp(mindmap);
this.session = session;
}
public User getUser() {
@ -54,24 +60,12 @@ public class LockInfo {
}
public long getSession() {
return session;
}
public void setSession(long session) {
this.session = session;
}
public long getTimestamp() {
return timestamp;
}
public long getPreviousTimestamp() {
return previousTimestamp;
}
public void updateTimestamp(@NotNull Mindmap mindmap) {
this.previousTimestamp = this.timestamp;
this.timestamp = mindmap.getLastModificationTime().getTimeInMillis();
@Override
public String toString() {
return "LockInfo{" +
"user=" + user +
", timeout=" + timeout +
", mapId=" + mapId +
'}';
}
}

View File

@ -1,26 +1,26 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import com.wisemapping.exceptions.AccessDeniedSecurityException;
import com.wisemapping.exceptions.LockException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.exceptions.SessionExpiredException;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import org.jetbrains.annotations.NotNull;
@ -30,16 +30,14 @@ public interface LockManager {
LockInfo getLockInfo(@NotNull Mindmap mindmap);
LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user);
void unlock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException, AccessDeniedSecurityException;
void unlockAll(@NotNull User user) throws LockException, AccessDeniedSecurityException;
boolean isLockedBy(@NotNull Mindmap mindmap, @NotNull User collaborator);
@NotNull
LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws WiseMappingException;
boolean isLockedBy(@NotNull Mindmap mindmap, @NotNull User user);
long generateSession();
@NotNull
LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException;
}

View File

@ -1,55 +1,39 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import com.wisemapping.exceptions.AccessDeniedSecurityException;
import com.wisemapping.exceptions.LockException;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.model.CollaborationRole;
import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/*
* Refresh page should not lost the lock.
* En caso que no sea posible grabar por que se perdio el lock, usar mensaje de error para explicar el por que...
* Mensaje modal explicando que el mapa esta siendo editado, por eso no es posible edilarlo....
* Internacionalizacion de los mensaje ...
* Logout limpiar las sessiones ...
*
* Casos:
* - Usuario pierde el lock:
* - Y grabo con la misma sessions y el timestap ok.
* - Y grabo con la misma session y el timestap esta mal
* - Y grabo con distinta sessions
* -
* - Usuario pierde el lock, pero intenta grabar camio
*/
class LockManagerImpl implements LockManager {
public static final int ONE_MINUTE_MILLISECONDS = 1000 * 60;
final Map<Integer, LockInfo> lockInfoByMapId;
final static Timer expirationTimer = new Timer();
private static final int ONE_MINUTE_MILLISECONDS = 1000 * 60;
private final Map<Integer, LockInfo> lockInfoByMapId;
private final static Timer expirationTimer = new Timer();
final private static Logger logger = Logger.getLogger(LockManagerImpl.class);
@Override
@ -62,23 +46,6 @@ class LockManagerImpl implements LockManager {
return lockInfoByMapId.get(mindmap.getId());
}
@Override
public LockInfo updateExpirationTimeout(@NotNull Mindmap mindmap, @NotNull User user) {
if (!this.isLocked(mindmap)) {
throw new IllegalStateException("Lock lost for map. No update possible.");
}
final LockInfo result = this.getLockInfo(mindmap);
if (!result.getUser().identityEquality(user)) {
throw new IllegalStateException("Could not update map lock timeout if you are not the locking user. User:" + result.getUser() + ", " + user);
}
result.updateTimeout();
result.updateTimestamp(mindmap);
logger.debug("Timeout updated for:" + mindmap.getId());
return result;
}
@Override
public void unlockAll(@NotNull final User user) throws LockException, AccessDeniedSecurityException {
final Set<Integer> mapIds = lockInfoByMapId.keySet();
@ -92,14 +59,7 @@ class LockManagerImpl implements LockManager {
@Override
public void unlock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException, AccessDeniedSecurityException {
if (isLocked(mindmap) && !isLockedBy(mindmap, user)) {
throw new LockException("Lock can be only revoked by the locker.");
}
if (!mindmap.hasPermissions(user, CollaborationRole.EDITOR)) {
throw new AccessDeniedSecurityException("Invalid lock, this should not happen");
}
verifyHasLock(mindmap, user);
this.unlock(mindmap.getId());
}
@ -124,53 +84,57 @@ class LockManagerImpl implements LockManager {
return System.nanoTime();
}
@Override
@NotNull
public LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user, long session) throws WiseMappingException {
@Override
public LockInfo lock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException {
if (isLocked(mindmap) && !isLockedBy(mindmap, user)) {
throw new LockException("Invalid lock, this should not happen");
}
if (!mindmap.hasPermissions(user, CollaborationRole.EDITOR)) {
throw new AccessDeniedSecurityException("Invalid lock, this should not happen");
throw LockException.createLockLost(mindmap, user, this);
}
// Do I need to create a new lock ?
LockInfo result = lockInfoByMapId.get(mindmap.getId());
if (result != null) {
// Update timeout only...
logger.debug("Update timestamp:" + mindmap.getId());
updateExpirationTimeout(mindmap, user);
// result.setSession(session);
} else {
logger.debug("Lock map id:" + mindmap.getId());
result = new LockInfo(user, mindmap, session);
if (result == null) {
logger.debug("Creating new lock for map id:" + mindmap.getId());
result = new LockInfo(user, mindmap);
lockInfoByMapId.put(mindmap.getId(), result);
}
// Update timestamp ...
logger.debug("Updating timeout:" + result);
result.updateTimeout();
return result;
}
private void verifyHasLock(@NotNull Mindmap mindmap, @NotNull User user) throws LockException, AccessDeniedSecurityException {
// Only editor can have lock ...
if (!mindmap.hasPermissions(user, CollaborationRole.EDITOR)) {
throw new AccessDeniedSecurityException(mindmap.getId(), user);
}
// Is the lock assigned to the user ...
if (isLocked(mindmap) && !isLockedBy(mindmap, user)) {
throw LockException.createLockLost(mindmap, user, this);
}
}
public LockManagerImpl() {
lockInfoByMapId = new ConcurrentHashMap<Integer, LockInfo>();
lockInfoByMapId = new ConcurrentHashMap<>();
expirationTimer.schedule(new TimerTask() {
@Override
public void run() {
logger.debug("Lock expiration scheduler started. Current locks:" + lockInfoByMapId.keySet());
final List<Integer> toRemove = new ArrayList<Integer>();
final Set<Integer> mapIds = lockInfoByMapId.keySet();
for (Integer mapId : mapIds) {
final LockInfo lockInfo = lockInfoByMapId.get(mapId);
if (lockInfo.isExpired()) {
toRemove.add(mapId);
}
synchronized (this) {
logger.debug("Lock expiration scheduler started. Current locks:" + lockInfoByMapId.keySet());
// Search for expired sessions and remove them ....
lockInfoByMapId.
keySet().
stream().
filter(mapId -> lockInfoByMapId.get(mapId).isExpired()).
forEach(mapId -> unlock(mapId));
}
for (Integer mapId : toRemove) {
unlock(mapId);
}
}
}, ONE_MINUTE_MILLISECONDS, ONE_MINUTE_MILLISECONDS);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import com.fasterxml.jackson.databind.ObjectMapper;

View File

@ -1,3 +1,20 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.service;
import org.springframework.validation.BindException;

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,5 +1,5 @@
/*
* Copyright [2015] [wisemapping]
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the

View File

@ -1,162 +0,0 @@
/*
* Copyright (c) 2008, Harald Walker (bitwalker.nl)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the
* following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* * Neither the name of bitwalker nor the names of its
* contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wisemapping.util;
/**
* Enum constants for internet applications like web-application and rich
* internet application.
*
* @author harald
*
*/
public enum Application {
HOTMAIL(Manufacturer.MICROSOFT, 1, "Windows Live Hotmail",
new String[] { "mail.live.com", "hotmail.msn" }, ApplicationType.WEBMAIL),
GMAIL( Manufacturer.GOOGLE, 5, "Gmail",
new String[] { "mail.google.com" }, ApplicationType.WEBMAIL),
YAHOO_MAIL( Manufacturer.YAHOO, 10, "Yahoo Mail",
new String[] { "mail.yahoo.com" }, ApplicationType.WEBMAIL),
COMPUSERVE( Manufacturer.COMPUSERVE, 20, "Compuserve",
new String[] { "csmail.compuserve.com" }, ApplicationType.WEBMAIL),
AOL_WEBMAIL( Manufacturer.AOL, 30, "AOL webmail",
new String[] { "webmail.aol.com" }, ApplicationType.WEBMAIL),
/**
* MobileMe webmail client by Apple. Previously known as .mac.
*/
MOBILEME( Manufacturer.APPLE, 40, "MobileMe",
new String[] { "www.me.com" }, ApplicationType.WEBMAIL),
/**
* Mail.com
* Mail.com provides consumers with web-based e-mail services
*/
MAIL_COM( Manufacturer.MMC, 50, "Mail.com",
new String[] { ".mail.com" }, ApplicationType.WEBMAIL),
/**
* Popular open source webmail client. Often installed by providers or privately.
*/
HORDE( Manufacturer.OTHER, 50, "horde",
new String[] { "horde" }, ApplicationType.WEBMAIL),
OTHER_WEBMAIL(Manufacturer.OTHER, 60, "Other webmail client",
new String[] { "webmail", "webemail" }, ApplicationType.WEBMAIL),
UNKNOWN(Manufacturer.OTHER, 0, "Unknown",
new String[0], ApplicationType.UNKNOWN);
private final short id;
private final String name;
private final String[] aliases;
private final ApplicationType applicationType;
private final Manufacturer manufacturer;
Application(Manufacturer manufacturer, int versionId, String name,
String[] aliases, ApplicationType applicationType) {
this.id = (short) ((manufacturer.getId() << 8) + (byte) versionId);
this.name = name;
this.aliases = aliases;
this.applicationType = applicationType;
this.manufacturer = manufacturer;
}
public short getId() {
return id;
}
public String getName() {
return name;
}
/**
* @return the applicationType
*/
public ApplicationType getApplicationType() {
return applicationType;
}
/**
* @return the manufacturer
*/
public Manufacturer getManufacturer() {
return manufacturer;
}
/*
* Checks if the given referrer string matches to the application. Only
* checks for one specific application.
*/
public boolean isInReferrerString(String referrerString) {
for (String alias : aliases) {
if (referrerString.toLowerCase().indexOf(alias.toLowerCase()) != -1)
return true;
}
return false;
}
/*
* Iterates over all Application to compare the signature with the referrer
* string. If no match can be found Application.UNKNOWN will be returned.
*/
public static Application parseReferrerString(String referrerString) {
// skip the empty and "-" referrer
if (referrerString != null && referrerString.length() > 1) {
for (Application applicationInList : Application.values()) {
if (applicationInList.isInReferrerString(referrerString))
return applicationInList;
}
}
return Application.UNKNOWN;
}
/**
* Returns the enum constant of this type with the specified id. Throws
* IllegalArgumentException if the value does not exist.
*
* @param id
* @return
*/
public static Application valueOf(short id) {
for (Application application : Application.values()) {
if (application.getId() == id)
return application;
}
// same behavior as standard valueOf(string) method
throw new IllegalArgumentException("No enum const for id " + id);
}
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2008, Harald Walker (bitwalker.nl)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the
* following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* * Neither the name of bitwalker nor the names of its
* contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wisemapping.util;
/**
* Enum constants classifying the different types of applications which are common in referrer strings
* @author harald
*
*/
public enum ApplicationType {
/**
* Webmail service like Windows Live Hotmail and Gmail.
*/
WEBMAIL("Webmail client"),
UNKNOWN("unknown");
private final String name;
ApplicationType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -1,351 +0,0 @@
/*
* Copyright (c) 2011, Harald Walker (bitwalker.nl)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the
* following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* * Neither the name of bitwalker nor the names of its
* contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.wisemapping.util;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Enum constants for most common browsers, including e-mail clients and bots.
*
* @author harald
*/
public enum Browser {
OPERA(Manufacturer.OPERA, null, 1, "Opera", new String[]{"Opera"}, null, BrowserType.WEB_BROWSER, RenderingEngine.PRESTO, "Opera\\/(([\\d]+)\\.([\\w]+))"), // before MSIE
OPERA_MINI(Manufacturer.OPERA, Browser.OPERA, 20, "Opera Mini", new String[]{"Opera Mini"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.PRESTO, null), // Opera for mobile devices
/**
* For some strange reason Opera uses 9.80 in the user-agent string.
*/
OPERA10(Manufacturer.OPERA, Browser.OPERA, 10, "Opera 10", new String[]{"Opera/9.8"}, null, BrowserType.WEB_BROWSER, RenderingEngine.PRESTO, "Version\\/(([\\d]+)\\.([\\w]+))"),
OPERA9(Manufacturer.OPERA, Browser.OPERA, 5, "Opera 9", new String[]{"Opera/9"}, null, BrowserType.WEB_BROWSER, RenderingEngine.PRESTO, null),
KONQUEROR(Manufacturer.OTHER, null, 1, "Konqueror", new String[]{"Konqueror"}, null, BrowserType.WEB_BROWSER, RenderingEngine.KHTML, "Konqueror\\/(([0-9]+)\\.?([\\w]+)?(-[\\w]+)?)"),
/**
* Outlook email client
*/
OUTLOOK(Manufacturer.MICROSOFT, null, 100, "Outlook", new String[]{"MSOffice"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.WORD, "MSOffice (([0-9]+))"), // before IE7
/**
* Microsoft Outlook 2007 identifies itself as MSIE7 but uses the html rendering engine of Word 2007.
* Example user agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 1.1.4322; MSOffice 12)
*/
OUTLOOK2007(Manufacturer.MICROSOFT, Browser.OUTLOOK, 107, "Outlook 2007", new String[]{"MSOffice 12"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.WORD, null), // before IE7
/**
* Outlook 2010 is still using the rendering engine of Word. http://www.fixoutlook.org
*/
OUTLOOK2010(Manufacturer.MICROSOFT, Browser.OUTLOOK, 108, "Outlook 2010", new String[]{"MSOffice 14"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.WORD, null), // before IE7
/**
* Family of Internet Explorer browsers
*/
IE11(Manufacturer.MICROSOFT, null, 1, "Internet Explorer", new String[]{") like Gecko"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, "Mozilla/5.0 (([\\d]+)\\.([\\w]+))"), // before Mozilla
/**
* Family of Internet Explorer browsers
*/
IE(Manufacturer.MICROSOFT, null, 1, "Internet Explorer", new String[]{"MSIE"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, "MSIE (([\\d]+)\\.([\\w]+))"), // before Mozilla
/**
* Since version 7 Outlook Express is identifying itself. By detecting Outlook Express we can not
* identify the Internet Explorer version which is probably used for the rendering.
* Obviously this product is now called Windows Live Mail Desktop or just Windows Live Mail.
*/
OUTLOOK_EXPRESS7(Manufacturer.MICROSOFT, Browser.IE, 110, "Windows Live Mail", new String[]{"Outlook-Express/7.0"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.TRIDENT, null), // before IE7, previously known as Outlook Express. First released in 2006, offered with different name later
/**
* Since 2007 the mobile edition of Internet Explorer identifies itself as IEMobile in the user-agent.
* If previous versions have to be detected, use the operating system information as well.
*/
IEMOBILE7(Manufacturer.MICROSOFT, Browser.IE, 121, "IE Mobile 7", new String[]{"IEMobile 7"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE strings
IEMOBILE6(Manufacturer.MICROSOFT, Browser.IE, 120, "IE Mobile 6", new String[]{"IEMobile 6"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE9(Manufacturer.MICROSOFT, Browser.IE, 90, "Internet Explorer 9", new String[]{"MSIE 9"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE8(Manufacturer.MICROSOFT, Browser.IE, 80, "Internet Explorer 8", new String[]{"MSIE 8"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE7(Manufacturer.MICROSOFT, Browser.IE, 70, "Internet Explorer 7", new String[]{"MSIE 7"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE6(Manufacturer.MICROSOFT, Browser.IE, 60, "Internet Explorer 6", new String[]{"MSIE 6"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE5_5(Manufacturer.MICROSOFT, Browser.IE, 55, "Internet Explorer 5.5", new String[]{"MSIE 5.5"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
IE5(Manufacturer.MICROSOFT, Browser.IE, 50, "Internet Explorer 5", new String[]{"MSIE 5"}, null, BrowserType.WEB_BROWSER, RenderingEngine.TRIDENT, null), // before MSIE
/**
* Google Chrome browser
*/
CHROME(Manufacturer.GOOGLE, null, 1, "Chrome", new String[]{"Chrome"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, "Chrome\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)"), // before Mozilla
CHROME10(Manufacturer.GOOGLE, Browser.CHROME, 15, "Chrome 10", new String[]{"Chrome/10"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), // before Mozilla
CHROME9(Manufacturer.GOOGLE, Browser.CHROME, 10, "Chrome 9", new String[]{"Chrome/9"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), // before Mozilla
CHROME8(Manufacturer.GOOGLE, Browser.CHROME, 5, "Chrome 8", new String[]{"Chrome/8"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), // before Mozilla
OMNIWEB(Manufacturer.OTHER, null, 2, "Omniweb", new String[]{"OmniWeb"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), //
SAFARI(Manufacturer.APPLE, null, 1, "Safari", new String[]{"Safari"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, "Version\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)"), // before AppleWebKit
SAFARI5(Manufacturer.APPLE, Browser.SAFARI, 3, "Safari 5", new String[]{"Version/5"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), // before AppleWebKit
MOBILE_SAFARI(Manufacturer.APPLE, Browser.SAFARI, 2, "Mobile Safari", new String[]{"Mobile Safari", "Mobile/"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.WEBKIT, null), // before Safari
SAFARI4(Manufacturer.APPLE, Browser.SAFARI, 4, "Safari 4", new String[]{"Version/4"}, null, BrowserType.WEB_BROWSER, RenderingEngine.WEBKIT, null), // before AppleWebKit
APPLE_MAIL(Manufacturer.APPLE, null, 50, "Apple Mail", new String[]{"AppleWebKit"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.WEBKIT, null), // Microsoft Entrourage/Outlook 2010 also only identifies itself as AppleWebKit
LOTUS_NOTES(Manufacturer.OTHER, null, 3, "Lotus Notes", new String[]{"Lotus-Notes"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.OTHER, "Lotus-Notes\\/(([\\d]+)\\.([\\w]+))"), // before Mozilla
/*
* Thunderbird email client, based on the same Gecko engine Firefox is using.
*/
THUNDERBIRD(Manufacturer.MOZILLA, null, 110, "Thunderbird", new String[]{"Thunderbird"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.GECKO, "Thunderbird\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)"), // using Gecko Engine
THUNDERBIRD3(Manufacturer.MOZILLA, Browser.THUNDERBIRD, 130, "Thunderbird 3", new String[]{"Thunderbird/3"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.GECKO, null), // using Gecko Engine
THUNDERBIRD2(Manufacturer.MOZILLA, Browser.THUNDERBIRD, 120, "Thunderbird 2", new String[]{"Thunderbird/2"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.GECKO, null), // using Gecko Engine
CAMINO(Manufacturer.OTHER, null, 5, "Camino", new String[]{"Camino"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, "Camino\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)"), // using Gecko Engine
CAMINO2(Manufacturer.OTHER, Browser.CAMINO, 17, "Camino 2", new String[]{"Camino/2"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
FLOCK(Manufacturer.OTHER, null, 4, "Flock", new String[]{"Flock"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, "Flock\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)"),
FIREFOX(Manufacturer.MOZILLA, null, 10, "Firefox", new String[]{"Firefox"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, "Firefox\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?(\\.[\\w]+)?)"), // using Gecko Engine
FIREFOX3MOBILE(Manufacturer.MOZILLA, Browser.FIREFOX, 31, "Firefox 3 Mobile", new String[]{"Firefox/3.5 Maemo"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
FIREFOX4(Manufacturer.MOZILLA, Browser.FIREFOX, 40, "Firefox 4", new String[]{"Firefox/4"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
FIREFOX3(Manufacturer.MOZILLA, Browser.FIREFOX, 30, "Firefox 3", new String[]{"Firefox/3"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
FIREFOX2(Manufacturer.MOZILLA, Browser.FIREFOX, 20, "Firefox 2", new String[]{"Firefox/2"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
FIREFOX1_5(Manufacturer.MOZILLA, Browser.FIREFOX, 15, "Firefox 1.5", new String[]{"Firefox/1.5"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, null), // using Gecko Engine
SEAMONKEY(Manufacturer.OTHER, null, 15, "SeaMonkey", new String[]{"SeaMonkey"}, null, BrowserType.WEB_BROWSER, RenderingEngine.GECKO, "SeaMonkey\\/(([0-9]+)\\.?([\\w]+)?(\\.[\\w]+)?)"), // using Gecko Engine
BOT(Manufacturer.OTHER, null, 12, "Robot/Spider", new String[]{"Mediapartners-Google", "Googlebot", "bot", "spider", "crawler", "Feedfetcher", "Slurp", "Twiceler", "Nutch", "BecomeBot"}, null, BrowserType.ROBOT, RenderingEngine.OTHER, null),
MOZILLA(Manufacturer.MOZILLA, null, 1, "Mozilla", new String[]{"Mozilla", "Moozilla"}, null, BrowserType.WEB_BROWSER, RenderingEngine.OTHER, null), // rest of the mozilla browsers
CFNETWORK(Manufacturer.OTHER, null, 6, "CFNetwork", new String[]{"CFNetwork"}, null, BrowserType.UNKNOWN, RenderingEngine.OTHER, null), // Mac OS X cocoa library
EUDORA(Manufacturer.OTHER, null, 7, "Eudora", new String[]{"Eudora", "EUDORA"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.OTHER, null), // email client by Qualcomm
POCOMAIL(Manufacturer.OTHER, null, 8, "PocoMail", new String[]{"PocoMail"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.OTHER, null),
THEBAT(Manufacturer.OTHER, null, 9, "The Bat!", new String[]{"The Bat"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.OTHER, null), // Email Client
NETFRONT(Manufacturer.OTHER, null, 10, "NetFront", new String[]{"NetFront"}, null, BrowserType.MOBILE_BROWSER, RenderingEngine.OTHER, null), // mobile device browser
EVOLUTION(Manufacturer.OTHER, null, 11, "Evolution", new String[]{"CamelHttpStream"}, null, BrowserType.EMAIL_CLIENT, RenderingEngine.OTHER, null), // http://www.go-evolution.org/Camel.Stream
LYNX(Manufacturer.OTHER, null, 13, "Lynx", new String[]{"Lynx"}, null, BrowserType.TEXT_BROWSER, RenderingEngine.OTHER, "Lynx\\/(([0-9]+)\\.([\\d]+)\\.?([\\w-+]+)?\\.?([\\w-+]+)?)"),
DOWNLOAD(Manufacturer.OTHER, null, 16, "Downloading Tool", new String[]{"cURL", "wget"}, null, BrowserType.TEXT_BROWSER, RenderingEngine.OTHER, null),
UNKNOWN(Manufacturer.OTHER, null, 14, "Unknown", new String[0], null, BrowserType.UNKNOWN, RenderingEngine.OTHER, null);
private final short id;
private final String name;
private final String[] aliases;
private final String[] excludeList; // don't match when these values are in the agent-string
private final BrowserType browserType;
private final Manufacturer manufacturer;
private final RenderingEngine renderingEngine;
private final Browser parent;
private final List<Browser> children;
private Pattern versionRegEx;
Browser(Manufacturer manufacturer, Browser parent, int versionId, String name, String[] aliases, String[] exclude, BrowserType browserType, RenderingEngine renderingEngine, String versionRegexString) {
this.id = (short) ((manufacturer.getId() << 8) + (byte) versionId);
this.name = name;
this.parent = parent;
this.children = new ArrayList<>();
if (this.parent != null) {
this.parent.children.add(this);
}
this.aliases = aliases;
this.excludeList = exclude;
this.browserType = browserType;
this.manufacturer = manufacturer;
this.renderingEngine = renderingEngine;
if (versionRegexString != null) {
this.versionRegEx = Pattern.compile(versionRegexString);
}
}
/**
* Iterates over all Browsers to compare the browser signature with
* the user agent string. If no match can be found Browser.UNKNOWN will
* be returned.
*
* @param agentString
* @return Browser
*/
public static Browser parseUserAgentString(String agentString) {
for (Browser browser : Browser.values()) {
// only check top level objects
if (browser.parent == null) {
Browser match = browser.checkUserAgent(agentString);
if (match != null) {
return match; // either current operatingSystem or a child object
}
}
}
return Browser.UNKNOWN;
}
/**
* Returns the enum constant of this type with the specified id.
* Throws IllegalArgumentException if the value does not exist.
*
* @param id
* @return
*/
public static Browser valueOf(short id) {
for (Browser browser : Browser.values()) {
if (browser.getId() == id)
return browser;
}
// same behavior as standard valueOf(string) method
throw new IllegalArgumentException(
"No enum const for id " + id);
}
public short getId() {
return id;
}
public String getName() {
return name;
}
private Pattern getVersionRegEx() {
if (this.versionRegEx == null) {
if (this.getGroup() != this)
return this.getGroup().getVersionRegEx();
else
return null;
}
return this.versionRegEx;
}
/**
* Detects the detailed version information of the browser. Depends on the userAgent to be available.
* Returns null if it can not detect the version information.
*
* @return Version
*/
public Version getVersion(String userAgentString) {
Pattern pattern = this.getVersionRegEx();
if (userAgentString != null && pattern != null) {
Matcher matcher = pattern.matcher(userAgentString);
if (matcher.find()) {
String fullVersionString = matcher.group(1);
String majorVersion = matcher.group(2);
String minorVersion = "0";
if (matcher.groupCount() > 2) // usually but not always there is a minor version
minorVersion = matcher.group(3);
return new Version(fullVersionString, majorVersion, minorVersion);
}
}
return null;
}
/**
* @return the browserType
*/
public BrowserType getBrowserType() {
return browserType;
}
/**
* @return the manufacturer
*/
public Manufacturer getManufacturer() {
return manufacturer;
}
/**
* @return the rendering engine
*/
public RenderingEngine getRenderingEngine() {
return renderingEngine;
}
/**
* @return top level browser family
*/
public Browser getGroup() {
if (this.parent != null) {
return parent.getGroup();
}
return this;
}
/*
* Checks if the given user-agent string matches to the browser.
* Only checks for one specific browser.
*/
public boolean isInUserAgentString(String agentString) {
for (String alias : aliases) {
if (agentString.toLowerCase().indexOf(alias.toLowerCase()) != -1)
return true;
}
return false;
}
/**
* Checks if the given user-agent does not contain one of the tokens which should not match.
* In most cases there are no excluding tokens, so the impact should be small.
*
* @param agentString
* @return
*/
private boolean containsExcludeToken(String agentString) {
if (excludeList != null) {
for (String exclude : excludeList) {
if (agentString.toLowerCase().indexOf(exclude.toLowerCase()) != -1)
return true;
}
}
return false;
}
private Browser checkUserAgent(String agentString) {
if (this.isInUserAgentString(agentString)) {
if (this.children.size() > 0) {
for (Browser childBrowser : this.children) {
Browser match = childBrowser.checkUserAgent(agentString);
if (match != null) {
return match;
}
}
}
// if children didn't match we continue checking the current to prevent false positives
if (!this.containsExcludeToken(agentString)) {
return this;
}
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More