clazz, final Object... initArguments)
&& clazz.isInstance(initArguments[0]) ? clazz.cast(initArguments[0]) : null;
}
+ /**
+ * Default provider for the ChatAPI
+ */
+ public static class DefaultChatAPIProvider implements ChatAPIProvider {
+
+ @Override
+ public ChatAPI getChatAPI(final Object... initArguments) {
+ if (Objects.nonNull(initArguments) && initArguments.length > 0 && initArguments[0] instanceof AppConfig) {
+ return new OpenAIChatAPIImpl((AppConfig) initArguments[0]);
+ }
+
+ throw new IllegalArgumentException("To create a ChatAPI you need to provide an AppConfig");
+ }
+ }
+
+ /**
+ * Default provider for the ImageAPI
+ */
+ public static class DefaultImageAPIProvider implements ImageAPIProvider {
+
+ @Override
+ public ImageAPI getImageAPI(final Object... initArguments) {
+ if (Objects.nonNull(initArguments) && initArguments.length >= 4
+ && initArguments[0] instanceof AppConfig
+ && (Objects.isNull(initArguments[1]) || initArguments[1] instanceof User)
+ ) {
+
+ final AppConfig config = (AppConfig) initArguments[0];
+ final User user = (User) initArguments[1];
+ final HostAPI hostApi = APILocator.getHostAPI();
+ final TempFileAPI tempFileApi = APILocator.getTempFileAPI();
+ return new OpenAIImageAPIImpl(config, user, hostApi, tempFileApi);
+ }
+
+ throw new IllegalArgumentException("To create an Image you need to provide an AppConfig");
+ }
+ }
+
+ /**
+ * Default provider for the CompletionsAPI
+ */
private static class DefaultCompletionsAPIProvider implements CompletionsAPIProvider {
@Override
@@ -47,6 +98,9 @@ private AppConfig unwrap(final Object... initArguments) {
}
}
+ /**
+ * Default provider for the EmbeddingsAPI
+ */
public static class DefaultEmbeddingsAPIProvider implements EmbeddingsAPIProvider {
@Override
@@ -72,19 +126,35 @@ public static final void setCurrentApiProviderName(final String apiName) {
* @param completionsAPI
*/
public static final void setDefaultCompletionsAPIProvider(final CompletionsAPIProvider completionsAPI) {
- completionsProviderMap.put("default", completionsAPI);
+ completionsProviderMap.put(DEFAULT, completionsAPI);
}
/**
- * Adds the default embeddings API Provider.
+ * Set the default embeddings API Provider.
* @param embeddingsAPI
*/
public static final void setDefaultEmbeddingsAPIProvider(final EmbeddingsAPIProvider embeddingsAPI) {
- embeddingsProviderMap.put("default", embeddingsAPI);
+ embeddingsProviderMap.put(DEFAULT, embeddingsAPI);
+ }
+
+ /**
+ * Set the default image API Provider.
+ * @param imageAPIProvider
+ */
+ public static final void setDefaultImageAPIProvider(final ImageAPIProvider imageAPIProvider) {
+ imageProviderMap.put(DEFAULT, imageAPIProvider);
+ }
+
+ /**
+ * Set the default chat API Provider.
+ * @param chatAPIProviderq
+ */
+ public static final void setDefaultChatAPIProvider(final ChatAPIProvider chatAPIProvider) {
+ chatProviderMap.put(DEFAULT, chatAPIProvider);
}
/**
- * Adds the default completions API provider.
+ * Adds completions API provider.
* @param completionsAPI
*/
public static final void addCompletionsAPIImplementation(final String apiName, final CompletionsAPIProvider completionsAPI) {
@@ -92,21 +162,49 @@ public static final void addCompletionsAPIImplementation(final String apiName, f
}
/**
- * Sets the default embeddings API provider.
+ * Adds default embeddings API provider.
* @param embeddingsAPI
*/
- public static final void addDefaultEmbeddingsAPIImplementation(final String apiName, final EmbeddingsAPIProvider embeddingsAPI) {
+ public static final void addEmbeddingsAPIImplementation(final String apiName, final EmbeddingsAPIProvider embeddingsAPI) {
embeddingsProviderMap.put(apiName, embeddingsAPI);
}
+ /**
+ * Adds default chat API provider.
+ * @param chatAPI
+ */
+ public static final void addChatAPIImplementation(final String apiName, final ChatAPIProvider chatAPI) {
+ chatProviderMap.put(apiName, chatAPI);
+ }
+
+ /**
+ * Adds default image API provider.
+ * @param imageAPI
+ */
+ public static final void addImageAPIImplementation(final String apiName, final ImageAPIProvider imageAPI) {
+ imageProviderMap.put(apiName, imageAPI);
+ }
+
@Override
- public CompletionsAPI getCompletionsAPI(Object... initArguments) {
+ public CompletionsAPI getCompletionsAPI(final Object... initArguments) {
return completionsProviderMap.get(currentApiProviderName.get()).getCompletionsAPI(initArguments);
}
@Override
- public EmbeddingsAPI getEmbeddingsAPI(Object... initArguments) {
+ public EmbeddingsAPI getEmbeddingsAPI(final Object... initArguments) {
return embeddingsProviderMap.get(currentApiProviderName.get()).getEmbeddingsAPI(initArguments);
}
+
+ @Override
+ public ChatAPI getChatAPI(final Object... initArguments) {
+
+ return chatProviderMap.get(currentApiProviderName.get()).getChatAPI(initArguments);
+ }
+
+ @Override
+ public ImageAPI getImageAPI(final Object... initArguments) {
+
+ return imageProviderMap.get(currentApiProviderName.get()).getImageAPI(initArguments);
+ }
}
diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java
similarity index 93%
rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java
rename to dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java
index d0fc19ee479f..cd7083d36510 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java
@@ -1,4 +1,4 @@
-package com.dotcms.ai.service;
+package com.dotcms.ai.api;
import com.dotcms.ai.model.AIImageRequestDTO;
import com.dotmarketing.util.json.JSONObject;
@@ -6,7 +6,7 @@
/**
* Service to interact with the OpenAI Image API
*/
-public interface OpenAIImageService {
+public interface ImageAPI {
/**
* Sends a text prompt to the OpenAI API.
diff --git a/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java
new file mode 100644
index 000000000000..c52773f2c5f8
--- /dev/null
+++ b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java
@@ -0,0 +1,11 @@
+package com.dotcms.ai.api;
+
+
+/**
+ * This class is in charge of providing the {@link ImageAPI}.
+ * @author jsanca
+ */
+public interface ImageAPIProvider {
+
+ ImageAPI getImageAPI(Object... initArguments);
+}
diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java
similarity index 87%
rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java
rename to dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java
index 08edb4d5d691..2e94dbe4218d 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java
@@ -1,4 +1,4 @@
-package com.dotcms.ai.service;
+package com.dotcms.ai.api;
import com.dotcms.ai.AiKeys;
import com.dotcms.ai.app.AppConfig;
@@ -12,11 +12,11 @@
import java.util.List;
import java.util.Map;
-public class OpenAIChatServiceImpl implements OpenAIChatService {
+public class OpenAIChatAPIImpl implements ChatAPI {
private final AppConfig config;
- public OpenAIChatServiceImpl(final AppConfig appConfig) {
+ public OpenAIChatAPIImpl(final AppConfig appConfig) {
this.config = appConfig;
}
@@ -47,7 +47,7 @@ public JSONObject sendTextPrompt(final String textPrompt) {
}
@VisibleForTesting
- String doRequest(final String urlIn, final JSONObject json) {
+ public String doRequest(final String urlIn, final JSONObject json) {
return OpenAIRequest.doRequest(urlIn, HttpMethod.POST, config, json);
}
diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java
similarity index 93%
rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java
rename to dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java
index 57b571dc140b..041a49b6e2d1 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java
@@ -1,4 +1,4 @@
-package com.dotcms.ai.service;
+package com.dotcms.ai.api;
import com.dotcms.ai.AiKeys;
import com.dotcms.ai.app.AppConfig;
@@ -29,7 +29,7 @@
import java.text.SimpleDateFormat;
import java.util.Date;
-public class OpenAIImageServiceImpl implements OpenAIImageService {
+public class OpenAIImageAPIImpl implements ImageAPI {
private static StopWordsUtil stopWordsUtil = StopWordsUtil.get();
@@ -38,10 +38,10 @@ public class OpenAIImageServiceImpl implements OpenAIImageService {
private final HostAPI hostApi;
private final TempFileAPI tempFileApi;
- public OpenAIImageServiceImpl(final AppConfig config,
- final User user,
- final HostAPI hostApi,
- final TempFileAPI tempFileApi) {
+ public OpenAIImageAPIImpl(final AppConfig config,
+ final User user,
+ final HostAPI hostApi,
+ final TempFileAPI tempFileApi) {
this.config = config;
this.user = user;
this.hostApi = hostApi;
@@ -173,22 +173,22 @@ private String generateFileName(final String originalPrompt) {
}
@VisibleForTesting
- String doRequest(final String urlIn, final JSONObject json) {
+ public String doRequest(final String urlIn, final JSONObject json) {
return OpenAIRequest.doRequest(urlIn, HttpMethod.POST, config, json);
}
@VisibleForTesting
- User getUser() {
+ public User getUser() {
return APILocator.systemUser();
}
@VisibleForTesting
- AIImageRequestDTO.Builder getDtoBuilder() {
+ public AIImageRequestDTO.Builder getDtoBuilder() {
return new AIImageRequestDTO.Builder();
}
public static void setStopWordsUtil(final StopWordsUtil stopWordsUtil) {
- OpenAIImageServiceImpl.stopWordsUtil = stopWordsUtil;
+ OpenAIImageAPIImpl.stopWordsUtil = stopWordsUtil;
}
}
diff --git a/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java b/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java
index 21903b41e291..375625d58adf 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java
@@ -5,8 +5,8 @@
import com.dotcms.ai.app.AppConfig;
import com.dotcms.ai.app.ConfigService;
import com.dotcms.ai.model.AIImageRequestDTO;
-import com.dotcms.ai.service.OpenAIImageService;
-import com.dotcms.ai.service.OpenAIImageServiceImpl;
+import com.dotcms.ai.api.ImageAPI;
+import com.dotcms.ai.api.OpenAIImageAPIImpl;
import com.dotcms.rest.WebResource;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.web.WebAPILocator;
@@ -113,7 +113,7 @@ public Response handleImageRequest(@Context final HttpServletRequest request,
.build();
}
- final OpenAIImageService service = new OpenAIImageServiceImpl(
+ final ImageAPI service = APILocator.getDotAIAPI().getImageAPI(
config,
user,
APILocator.getHostAPI(),
diff --git a/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java b/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java
index 7891263733e4..050b56b1e535 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java
@@ -3,10 +3,10 @@
import com.dotcms.ai.AiKeys;
import com.dotcms.ai.app.AppConfig;
import com.dotcms.ai.app.ConfigService;
-import com.dotcms.ai.service.OpenAIChatService;
-import com.dotcms.ai.service.OpenAIChatServiceImpl;
-import com.dotcms.ai.service.OpenAIImageService;
-import com.dotcms.ai.service.OpenAIImageServiceImpl;
+import com.dotcms.ai.api.ChatAPI;
+import com.dotcms.ai.api.OpenAIChatAPIImpl;
+import com.dotcms.ai.api.ImageAPI;
+import com.dotcms.ai.api.OpenAIImageAPIImpl;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.web.WebAPILocator;
import com.dotmarketing.util.json.JSONObject;
@@ -28,8 +28,8 @@ public class AIViewTool implements ViewTool {
private ViewContext context;
private AppConfig config;
- private OpenAIChatService chatService;
- private OpenAIImageService imageService;
+ private ChatAPI chatService;
+ private ImageAPI imageService;
@Override
public void init(final Object obj) {
@@ -127,13 +127,13 @@ User user() {
}
@VisibleForTesting
- OpenAIChatService chatService() {
- return new OpenAIChatServiceImpl(config);
+ ChatAPI chatService() {
+ return APILocator.getDotAIAPI().getChatAPI(config);
}
@VisibleForTesting
- OpenAIImageService imageService() {
- return new OpenAIImageServiceImpl(config, user(), APILocator.getHostAPI(), APILocator.getTempFileAPI());
+ ImageAPI imageService() {
+ return APILocator.getDotAIAPI().getImageAPI(config, user(), APILocator.getHostAPI(), APILocator.getTempFileAPI());
}
private Try generate(final P prompt, final Function serviceCall) {
diff --git a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java
index b1ef5eac9b75..8ded9b0bc9f1 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java
@@ -38,7 +38,6 @@ public String getHowTo() {
@Override
public void executeAction(WorkflowProcessor processor, Map params) throws WorkflowActionFailureException {
-
final Runnable task = new OpenAIGenerateImageRunner(processor, params);
task.run();
}
diff --git a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java
index 29c3af893417..aa8260b1e4cb 100644
--- a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java
+++ b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java
@@ -1,16 +1,21 @@
package com.dotcms.ai.workflow;
+import com.dotcms.ai.api.ImageAPI;
import com.dotcms.ai.app.ConfigService;
-import com.dotcms.ai.service.OpenAIImageService;
-import com.dotcms.ai.service.OpenAIImageServiceImpl;
import com.dotcms.ai.util.VelocityContextFactory;
+import com.dotcms.api.system.event.message.MessageSeverity;
+import com.dotcms.api.system.event.message.MessageType;
+import com.dotcms.api.system.event.message.SystemMessageEventUtil;
+import com.dotcms.api.system.event.message.builder.SystemMessageBuilder;
import com.dotcms.api.web.HttpServletRequestThreadLocal;
import com.dotcms.contenttype.model.field.BinaryField;
import com.dotcms.contenttype.model.field.Field;
import com.dotcms.contenttype.model.type.ContentType;
+import com.dotcms.exception.ExceptionUtil;
import com.dotcms.rendering.velocity.util.VelocityUtil;
import com.dotmarketing.beans.Host;
import com.dotmarketing.business.APILocator;
+import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.dotmarketing.portlets.workflows.model.WorkflowActionClassParameter;
import com.dotmarketing.portlets.workflows.model.WorkflowProcessor;
@@ -22,6 +27,8 @@
import org.apache.velocity.context.Context;
import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -30,60 +37,43 @@
* It implements the AsyncWorkflowRunner interface and overrides its methods to provide the functionality needed.
* This class is designed to handle long-running tasks in a separate thread and needs to be serialized to a persistent storage.
*/
-public class OpenAIGenerateImageRunner implements AsyncWorkflowRunner {
+public class OpenAIGenerateImageRunner implements Runnable {
- final String identifier;
- final long language;
- final User user;
- final String prompt;
- final boolean overwriteField;
- final String fieldToWrite;
- final long runAt;
+ private final User user;
+ private final String prompt;
+ private final boolean overwriteField;
+ private final String fieldToWrite;
+ private final Contentlet contentlet;
- OpenAIGenerateImageRunner(WorkflowProcessor processor, Map params) {
+
+ public OpenAIGenerateImageRunner(final WorkflowProcessor processor, final Map params) {
this(
processor.getContentlet(),
processor.getUser(),
params.get(OpenAIParams.OPEN_AI_PROMPT.key).getValue(),
Try.of(() -> Boolean.parseBoolean(params.get(OpenAIParams.OVERWRITE_FIELDS.key).getValue()))
.getOrElse(false),
- params.get(OpenAIParams.FIELD_TO_WRITE.key).getValue(),
- Try.of(() -> Integer.parseInt(params.get(OpenAIParams.RUN_DELAY.key).getValue())).getOrElse(5)
+ params.get(OpenAIParams.FIELD_TO_WRITE.key).getValue()
);
}
- OpenAIGenerateImageRunner(final Contentlet contentlet,
+ public OpenAIGenerateImageRunner(final Contentlet contentlet,
final User user,
final String prompt,
final boolean overwriteField,
- final String fieldToWrite,
- final int runDelay) {
- this.identifier = contentlet.getIdentifier();
- this.language = contentlet.getLanguageId();
+ final String fieldToWrite) {
+
+ this.contentlet = contentlet;
this.prompt = prompt;
this.overwriteField = overwriteField;
this.fieldToWrite = fieldToWrite;
this.user = user;
- this.runAt = System.currentTimeMillis() + runDelay;
- }
-
- @Override
- public long getRunAt() {
- return this.runAt;
- }
-
- @Override
- public String getIdentifier() {
- return this.identifier;
}
@Override
- public long getLanguage() {
- return this.language;
- }
+ public void run() {
- public void runInternal() {
- final Contentlet workingContentlet = getLatest(identifier, language, user);
+ final Contentlet workingContentlet = this.contentlet;
final Host host = Try.of(
() -> APILocator.getHostAPI().find(workingContentlet.getHost(), APILocator.systemUser(), true))
.getOrElse(APILocator.systemHost());
@@ -120,27 +110,25 @@ public void runInternal() {
}
final String finalPrompt = VelocityUtil.eval(prompt, ctx);
- final OpenAIImageService service = new OpenAIImageServiceImpl(
+ final ImageAPI imageAPI = APILocator.getDotAIAPI().getImageAPI(
ConfigService.INSTANCE.config(host),
user,
APILocator.getHostAPI(),
APILocator.getTempFileAPI());
- final JSONObject resp = Try.of(() -> service.sendTextPrompt(finalPrompt))
+ final JSONObject resp = Try.of(() -> imageAPI.sendTextPrompt(finalPrompt))
.onFailure(e -> Logger.warn(OpenAIGenerateImageRunner.class, "error generating image:" + e))
.getOrElse(JSONObject::new);
- final String tempFile = resp.optString("response");
- if (UtilMethods.isEmpty(tempFile)) {
+ final String tempFile = resp.optString("tempFile");
+ if (UtilMethods.isEmpty(tempFile) && !new File(tempFile).exists()) {
Logger.warn(
this.getClass(),
"Unable to generate image for contentlet: " + workingContentlet.getTitle());
return;
}
- final Contentlet contentToSave = checkoutLatest(identifier, language, user);
- contentToSave.setProperty(fieldToTry.get().variable(), tempFile);
- saveContentlet(contentToSave, user);
+ contentlet.setProperty(fieldToTry.get().variable(), new File(tempFile));
} catch (Exception e) {
handleError(e, user);
} finally{
@@ -150,7 +138,29 @@ public void runInternal() {
}
}
+ /**
+ * Handles any exceptions that occur during the execution of the workflow.
+ * It logs the error, sends a system message to the user, and rethrows the exception as a DotRuntimeException.
+ *
+ * @param e the exception that occurred.
+ * @param user the user who is running the workflow.
+ * @throws DotRuntimeException if an exception occurs during the execution of the workflow.
+ */
+ private void handleError(final Exception e, final User user) {
+
+ final String errorMsg = String.format("Error: %s", ExceptionUtil.getErrorMessage(e));
+ final SystemMessageBuilder message = new SystemMessageBuilder()
+ .setMessage(errorMsg)
+ .setLife(5000)
+ .setType(MessageType.SIMPLE_MESSAGE)
+ .setSeverity(MessageSeverity.ERROR);
+ SystemMessageEventUtil.getInstance().pushMessage(message.create(), List.of(user.getUserId()));
+ Logger.error(this.getClass(), errorMsg, e);
+ throw new DotRuntimeException(e);
+ }
+
private Optional resolveField(final Contentlet contentlet) {
+
final ContentType type = contentlet.getContentType();
final Optional fieldToTry = Try.of(() -> type.fieldMap().get(this.fieldToWrite)).toJavaOptional();
if (UtilMethods.isSet(this.fieldToWrite)) {
diff --git a/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java b/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java
index f27bbf3fe8ce..93ee80d3ed3b 100644
--- a/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java
+++ b/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java
@@ -5,7 +5,6 @@
import com.dotcms.business.WrapInTransaction;
import com.dotcms.util.EnterpriseFeature;
import com.dotcms.util.LogTime;
-import com.dotmarketing.util.Logger;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
@@ -23,6 +22,8 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
@@ -39,6 +40,9 @@
*/
public class ByteBuddyFactory {
+ // Use base log4j logger here to prevent recursive issues with internal Logger class
+ private static final Logger LOGGER = LogManager.getLogger(ByteBuddyFactory.class);
+
private static final AtomicBoolean agentLoaded = new AtomicBoolean(false);
private static final Map, Class>> adviceMap = Map.of(
WrapInTransaction.class, WrapInTransactionAdvice.class,
@@ -69,16 +73,16 @@ public static void init() {
if (!agentLoaded.get()) {
try {
premain(null, ByteBuddyAgent.install());
- Logger.info(ByteBuddyFactory.class, "Loaded ByteBuddy Advice");
+ LOGGER.info("Loaded ByteBuddy Advice");
} catch (Exception e) {
- Logger.error(ByteBuddyFactory.class, "Cannot install ByteBuddy Advice");
+ LOGGER.error("Cannot install ByteBuddy Advice");
}
}
}
public static void premain(final String arg, final Instrumentation inst) throws Exception {
- Logger.info(ByteBuddyFactory.class, "Starting ByteBuddy Agent");
+ LOGGER.info("Starting ByteBuddy Agent");
if (!agentLoaded.compareAndSet(false, true)) {
return;
}
@@ -122,9 +126,9 @@ public ClassFileLocator classFileLocator(final ClassLoader classLoader, final Ja
})
.installOn(inst);
- Logger.info(ByteBuddyFactory.class, "ByteBuddy Initialized");
+ LOGGER.info("ByteBuddy Initialized");
} catch (Exception e) {
- Logger.error(ByteBuddyFactory.class, "Error Initializing ByteBuddy", e);
+ LOGGER.error("Error Initializing ByteBuddy", e);
}
diff --git a/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java b/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java
index 74120fa57866..90dba56eac3b 100644
--- a/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java
+++ b/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java
@@ -96,10 +96,12 @@ public void attributeReplaced(HttpSessionBindingEvent event) {
public void sessionCreated(final HttpSessionEvent event) {
// Not implemented
+ Logger.debug(this, "Session created");
}
public void sessionDestroyed(final HttpSessionEvent event) {
+ Logger.debug(this, "Session destroyed");
final String userId = (String) event.getSession().getAttribute(com.liferay.portal.util.WebKeys.USER_ID);
if (userId != null) {
diff --git a/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java b/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java
index 431664eefd32..0cf3775d0d0c 100644
--- a/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java
+++ b/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java
@@ -7,10 +7,8 @@
import com.dotcms.util.AsciiArt;
import com.dotmarketing.business.CacheLocator;
import com.dotmarketing.common.reindex.ReindexThread;
-import com.dotmarketing.loggers.Log4jUtil;
import com.dotmarketing.quartz.QuartzUtils;
import com.dotmarketing.util.Config;
-import com.dotmarketing.util.ConfigUtils;
import com.dotmarketing.util.Logger;
import io.vavr.control.Try;
@@ -18,7 +16,6 @@
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.websocket.server.ServerContainer;
-import java.io.File;
/**
*
@@ -62,25 +59,6 @@ public void contextInitialized(ServletContextEvent arg0) {
Config.setMyApp(arg0.getServletContext());
-
- String path = null;
- try {
-
- String contextPath = Config.CONTEXT.getRealPath("/");
- if ( !contextPath.endsWith( File.separator ) ) {
- contextPath += File.separator;
- }
- File file = new File(contextPath + "WEB-INF" + File.separator + "log4j" + File.separator + "log4j2.xml");
- path = file.toURI().toString();
-
- } catch (Exception e) {
- Logger.error(this,e.getMessage(),e);
- }
-
- //Initialises/reconfigures log4j based on a given log4j configuration file
- Log4jUtil.initializeFromPath(path);
-
-
installWebSocket(arg0.getServletContext());
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java b/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java
index ac941ba8604d..61d44a6929fd 100644
--- a/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java
+++ b/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java
@@ -27,15 +27,6 @@ public class Log4jUtil {
private final static String LOG4J_CONTEXT_SELECTOR = "Log4jContextSelector";
- /**
- * Configure default system properties
- */
- public static void configureDefaultSystemProperties () {
- if(!UtilMethods.isSet(System.getProperty(LOG4J_CONTEXT_SELECTOR))) {
- System.setProperty(LOG4J_CONTEXT_SELECTOR, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
- }
- }
-
/**
* Creates a ConsoleAppender in order to add it to the root logger
*/
@@ -128,33 +119,6 @@ public static void shutdown(LoggerContext context) {
Configurator.shutdown(context);
}
- /**
- * Initialises/reconfigures log4j based on a given log4j configuration file
- *
- * @param log4jConfigFilePath
- */
- public static void initializeFromPath ( String log4jConfigFilePath ) {
-
- if ( log4jConfigFilePath != null ) {
-
- try {
-
- configureDefaultSystemProperties();
- LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
-
- if ( !loggerContext.isInitialized() || loggerContext.isStopped() ) {
- Configurator.initialize(null, log4jConfigFilePath);
- } else {
- loggerContext.setConfigLocation(URI.create(log4jConfigFilePath));
- loggerContext.reconfigure();
- }
- } catch ( Exception e ) {
- LogManager.getLogger().error("Error initializing log for " + log4jConfigFilePath + " configuration file.", e);
- }
- LogManager.getLogger().info("Async Logger enabled: "+ AsyncLoggerContextSelector.isSelected());
- }
- }
-
/**
* Returns the current dotCMS logger context
*
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java
index 25abb2a82089..a53a6a6f3b8b 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java
@@ -135,7 +135,7 @@ public void remove(final String key){
Logger.debug(this, "Cache not able to be removed", e);
}
- final Host host = CacheLocator.getHostCache().get(key);
+ final Host host = CacheLocator.getHostCache().getById(key);
if(host != null){
CacheLocator.getHostCache().remove(host);
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java
index ffa71a1a0709..504083e15fbe 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java
@@ -121,11 +121,15 @@ public Host findDefaultHost(User user, boolean respectFrontendRoles) throws DotS
@Override
@CloseDBIfOpened
public Host resolveHostName(String serverName, User user, boolean respectFrontendRoles) throws DotDataException, DotSecurityException {
- Host host = hostCache.getHostByAlias(serverName);
- User systemUser = APILocator.systemUser();
-
- if(host == null){
-
+ Host host;
+ final Host cachedHostByAlias = hostCache.getHostByAlias(serverName);
+ if (UtilMethods.isSet(() -> cachedHostByAlias.getIdentifier())) {
+ if (HostCache.CACHE_404_HOST.equals(cachedHostByAlias.getIdentifier())) {
+ return null;
+ }
+ host = cachedHostByAlias;
+ } else {
+ final User systemUser = APILocator.systemUser();
try {
final Optional optional = resolveHostNameWithoutDefault(serverName, systemUser, respectFrontendRoles);
host = optional.isPresent() ? optional.get() : findDefaultHost(systemUser, respectFrontendRoles);
@@ -133,12 +137,15 @@ public Host resolveHostName(String serverName, User user, boolean respectFronten
host = findDefaultHost(systemUser, respectFrontendRoles);
}
- if(host != null){
+ if (host != null) {
hostCache.addHostAlias(serverName, host);
+ } else {
+ hostCache.addHostAlias(serverName, HostCache.cache404Contentlet);
}
}
-
- checkSitePermission(user, respectFrontendRoles, host);
+ if (host != null) {
+ checkSitePermission(user, respectFrontendRoles, host);
+ }
return host;
}
@@ -146,17 +153,24 @@ public Host resolveHostName(String serverName, User user, boolean respectFronten
@CloseDBIfOpened
public Optional resolveHostNameWithoutDefault(String serverName, User user, boolean respectFrontendRoles) throws DotDataException, DotSecurityException {
- Host host = hostCache.getHostByAlias(serverName);
- User systemUser = APILocator.systemUser();
-
- if(host == null){
+ Host host;
+ final Host cachedHostByAlias = hostCache.getHostByAlias(serverName);
+ if (UtilMethods.isSet(() -> cachedHostByAlias.getIdentifier())) {
+ if (HostCache.CACHE_404_HOST.equals(cachedHostByAlias.getIdentifier())) {
+ return Optional.empty();
+ }
+ host = cachedHostByAlias;
+ } else {
+ User systemUser = APILocator.systemUser();
host = findByNameNotDefault(serverName, systemUser, respectFrontendRoles);
if(host == null){
host = findByAlias(serverName, systemUser, respectFrontendRoles);
}
- if(host != null){
+ if (host == null) {
+ hostCache.addHostAlias(serverName, HostCache.cache404Contentlet);
+ } else {
hostCache.addHostAlias(serverName, host);
}
}
@@ -297,7 +311,14 @@ public Host find(final String id, final User user,
return findSystemHost();
}
- Host site = hostCache.get(id);
+ Host site = null;
+ Host cachedSiteById = hostCache.getById(id);
+ if (UtilMethods.isSet(() -> cachedSiteById.getIdentifier())) {
+ if (HostCache.CACHE_404_HOST.equals(cachedSiteById.getIdentifier())) {
+ return null;
+ }
+ site = cachedSiteById;
+ }
if (site == null) {
site = DBSearch(id,user,respectFrontendRoles);
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java
index a11feef5d0c2..780970871eae 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java
@@ -8,10 +8,23 @@
public abstract class HostCache implements Cachable{
protected static String PRIMARY_GROUP = "HostCache";
protected static String ALIAS_GROUP = "HostAliasCache";
-
+ protected static String NOT_FOUND_BY_ID_GROUP = "Host404ByIdCache";
+ protected static String NOT_FOUND_BY_NAME_GROUP = "Host404ByNameCache";
+
+ public static final String CACHE_404_HOST = "CACHE_404_HOST";
+
+ protected static final Host cache404Contentlet = new Host() {
+ @Override
+ public String getIdentifier() {
+ return CACHE_404_HOST;
+ }
+ };
+
abstract protected Host add(Host host);
- abstract protected Host get(String key);
+ abstract protected Host getById(String id);
+
+ abstract protected Host getByName(String name);
abstract public void clearCache();
@@ -26,5 +39,10 @@ public abstract class HostCache implements Cachable{
abstract protected Host getHostByAlias(String alias);
abstract protected void addHostAlias(String alias, Host host);
+
+ abstract protected void add404HostById(String id);
+
+ abstract protected void add404HostByName(String name);
+
abstract protected void clearAliasCache() ;
}
\ No newline at end of file
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java
index 983678e2d903..38d7d363e2c0 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java
@@ -23,7 +23,9 @@ public class HostCacheImpl extends HostCache {
// region's name for the cache
- private String[] groupNames = {PRIMARY_GROUP, ALIAS_GROUP};
+ private final String[] groupNames = {
+ PRIMARY_GROUP, ALIAS_GROUP, NOT_FOUND_BY_ID_GROUP, NOT_FOUND_BY_NAME_GROUP
+ };
public HostCacheImpl() {
cache = CacheLocator.getCacheAdministrator();
@@ -37,6 +39,9 @@ protected Host add(Host host) {
String key = host.getIdentifier();
String key2 =host.getHostname();
+ cache.remove(key, NOT_FOUND_BY_ID_GROUP);
+ cache.remove(key2, NOT_FOUND_BY_NAME_GROUP);
+
// Add the key to the cache
cache.put(key, host,PRIMARY_GROUP);
cache.put(key2, host,PRIMARY_GROUP);
@@ -72,7 +77,10 @@ protected Host getHostByAlias(String key) {
Host host = null;
try{
String hostId = (String) cache.get(key,ALIAS_GROUP);
- host = get(hostId);
+ if (CACHE_404_HOST.equals(hostId)) {
+ return cache404Contentlet;
+ }
+ host = get(hostId, NOT_FOUND_BY_ID_GROUP);
if(host == null){
cache.remove(key, ALIAS_GROUP);
}
@@ -83,10 +91,17 @@ protected Host getHostByAlias(String key) {
return host;
}
- protected Host get(String key) {
+ private Host get(String key, String notFoundCacheGroup) {
Host host = null;
try{
- host = (Host) cache.get(key,PRIMARY_GROUP);
+ if (UtilMethods.isSet(notFoundCacheGroup)) {
+ host = (Host) cache.get(key, notFoundCacheGroup);
+ }
+ if (host != null && CACHE_404_HOST.equals(host.getIdentifier())) {
+ return cache404Contentlet;
+ } else {
+ host = (Host) cache.get(key, PRIMARY_GROUP);
+ }
}catch (DotCacheException e) {
Logger.debug(this, "Cache Entry not found", e);
}
@@ -94,13 +109,37 @@ protected Host get(String key) {
return host;
}
- /* (non-Javadoc)
+ /**
+ * Get a host by id
+ * @param id the id of the host
+ * @return the host or 404 if the host is in the not found cache,
+ * null if the host is not found in the cache
+ */
+ @Override
+ protected Host getById(final String id) {
+ return get(id, NOT_FOUND_BY_ID_GROUP);
+ }
+
+ /**
+ * Get a host by name
+ * @param name the name of the host
+ * @return the host or 404 if the host is in the not found cache,
+ * null if the host is not found in the cache
+ */
+ @Override
+ protected Host getByName(final String name) {
+ return get(name, NOT_FOUND_BY_NAME_GROUP);
+ }
+
+ /* (non-Javadoc)
* @see com.dotmarketing.business.PermissionCache#clearCache()
*/
public void clearCache() {
// clear the cache
cache.flushGroup(PRIMARY_GROUP);
cache.flushGroup(ALIAS_GROUP);
+ cache.flushGroup(NOT_FOUND_BY_ID_GROUP);
+ cache.flushGroup(NOT_FOUND_BY_NAME_GROUP);
}
/* (non-Javadoc)
@@ -114,21 +153,19 @@ protected void remove(Host host){
String _defaultHost =PRIMARY_GROUP +DEFAULT_HOST;
cache.remove(_defaultHost,PRIMARY_GROUP);
- //remove aliases from host in cache
- Host h = get(host.getIdentifier());
-
-
String key = host.getIdentifier();
String key2 = host.getHostname();
try{
cache.remove(key,PRIMARY_GROUP);
+ cache.remove(key,NOT_FOUND_BY_ID_GROUP);
}catch (Exception e) {
Logger.debug(this, "Cache not able to be removed", e);
}
try{
cache.remove(key2,PRIMARY_GROUP);
+ cache.remove(key2, NOT_FOUND_BY_NAME_GROUP);
}catch (Exception e) {
Logger.debug(this, "Cache not able to be removed", e);
}
@@ -147,7 +184,7 @@ public String getPrimaryGroup() {
protected Host getDefaultHost(){
- return get(DEFAULT_HOST);
+ return get(DEFAULT_HOST, null);
}
protected void addHostAlias(String alias, Host host){
@@ -155,8 +192,29 @@ protected void addHostAlias(String alias, Host host){
cache.put(alias, host.getIdentifier(),ALIAS_GROUP);
}
}
-
-
+
+ /**
+ * Add the host id to the 404 (not found) cache
+ * @param id the id of the host
+ */
+ @Override
+ protected void add404HostById(String id) {
+ if (id != null) {
+ cache.put(id, cache404Contentlet, NOT_FOUND_BY_ID_GROUP);
+ }
+ }
+
+ /**
+ * Add the host name to the 404 (not found) cache
+ * @param name the name of the host
+ */
+ @Override
+ protected void add404HostByName(String name) {
+ if (name != null) {
+ cache.put(name, cache404Contentlet, NOT_FOUND_BY_NAME_GROUP);
+ }
+ }
+
protected void clearAliasCache() {
// clear the alias cache
cache.flushGroup(ALIAS_GROUP);
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java
index e1901a3a1f23..3c4e7132ad9f 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java
@@ -189,8 +189,14 @@ protected ContentletAPI getContentletAPI() {
@Override
public Host bySiteName(final String siteName) {
- Host site = siteCache.get(siteName);
- if (null == site || !UtilMethods.isSet(site.getIdentifier())) {
+ Host site;
+ final Host cachedSiteByName = siteCache.getByName(siteName);;
+ if (UtilMethods.isSet(() -> cachedSiteByName.getIdentifier())) {
+ if (HostCache.CACHE_404_HOST.equals(cachedSiteByName.getIdentifier())) {
+ return null;
+ }
+ site = cachedSiteByName;
+ } else {
final DotConnect dc = new DotConnect();
final StringBuilder sqlQuery = new StringBuilder().append(SELECT_SITE_INODE)
.append(WHERE);
@@ -200,6 +206,7 @@ public Host bySiteName(final String siteName) {
try {
final List