diff --git a/code/pom.xml b/code/pom.xml index 884ef26..d61bb09 100644 --- a/code/pom.xml +++ b/code/pom.xml @@ -227,7 +227,7 @@ org.jetbrains annotations - 22.0.0 + 24.0.1 junit diff --git a/code/src/main/java/org/nocturne/caption/CaptionsImpl.java b/code/src/main/java/org/nocturne/caption/CaptionsImpl.java index 5e6f0a9..daa8d28 100644 --- a/code/src/main/java/org/nocturne/caption/CaptionsImpl.java +++ b/code/src/main/java/org/nocturne/caption/CaptionsImpl.java @@ -4,6 +4,7 @@ package org.nocturne.caption; import com.google.inject.Singleton; +import org.apache.log4j.Logger; import org.nocturne.exception.ConfigurationException; import org.nocturne.main.ApplicationContext; @@ -31,6 +32,8 @@ */ @Singleton public class CaptionsImpl implements Captions { + private static final Logger logger = Logger.getLogger(CaptionsImpl.class); + private static final Pattern CAPTIONS_FILE_PATTERN = Pattern.compile("captions_[\\w]{2}\\.properties"); /** @@ -135,6 +138,7 @@ private static void save(Properties properties, String language) { properties.store(writer, null); writer.close(); } catch (IOException e) { + logger.error("Can't write into file " + file + '.', e); throw new ConfigurationException("Can't write into file " + file + '.', e); } } @@ -166,6 +170,7 @@ private void loadPropertiesForProduction() { reader.close(); propertiesMap.put(language, properties); } catch (IOException e) { + logger.error("Can't load caption properties for language " + language + '.', e); throw new ConfigurationException("Can't load caption properties for language " + language + '.', e); } } diff --git a/code/src/main/java/org/nocturne/link/Links.java b/code/src/main/java/org/nocturne/link/Links.java index ed8c573..be9c133 100644 --- a/code/src/main/java/org/nocturne/link/Links.java +++ b/code/src/main/java/org/nocturne/link/Links.java @@ -43,6 +43,8 @@ * @author Mike Mirzayanov */ public class Links { + private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(Links.class); + private static final Lock addLinkLock = new ReentrantLock(); private static final int INTERCEPTOR_MAX_PERMIT_COUNT = 8 * Runtime.getRuntime().availableProcessors(); @@ -107,6 +109,8 @@ public static String getLinkName(@Nonnull Class pageClass) { } if (clazz == null) { + logger.error("Page class should have @Link or @LinkSet annotation, but " + + pageClass.getName() + " hasn't."); throw new NocturneException("Page class should have @Link or @LinkSet annotation, but " + pageClass.getName() + " hasn't."); } @@ -131,6 +135,7 @@ public static void add(Class clazz, List linkSet) { try { String name = getLinkName(clazz); if (classesByName.containsKey(name) && !clazz.equals(classesByName.get(name))) { + logger.error("Can't add page which is not unique by it's name: " + clazz.getName() + '.'); throw new ConfigurationException("Can't add page which is not unique by it's name: " + clazz.getName() + '.'); } @@ -151,10 +156,12 @@ public static void add(Class clazz, List linkSet) { for (Map linkMap : linksByPage.values()) { if (linkMap.containsKey(pageLink)) { + logger.error("Page link \"" + pageLink + "\" already registered."); throw new ConfigurationException("Page link \"" + pageLink + "\" already registered."); } } if (links.containsKey(pageLink)) { + logger.error("Page link \"" + pageLink + "\" already registered."); throw new ConfigurationException("Page link \"" + pageLink + "\" already registered."); } @@ -176,6 +183,7 @@ public static void add(Class clazz, List linkSet) { public static void add(Class clazz) { List linkSet = getLinksViaReflection(clazz); if (linkSet.isEmpty()) { + logger.error("Can't find link for page " + clazz.getName() + '.'); throw new ConfigurationException("Can't find link for page " + clazz.getName() + '.'); } @@ -227,11 +235,12 @@ public static String getLinkByMap(Class clazz, @Nullable String if (bestMatchedLinkSections == null) { if (linkName == null || linkName.isEmpty()) { + logger.error("Can't find link for page " + clazz.getName() + '.'); throw new NoSuchLinkException("Can't find link for page " + clazz.getName() + '.'); } else { - throw new NoSuchLinkException( - "Can't find link with name \'" + linkName + "\' for page " + clazz.getName() + '.' - ); + logger.error("Can't find link with name '" + linkName + "' for page " + clazz.getName() + '.'); + throw new NoSuchLinkException("Can't find link with name '" + + linkName + "' for page " + clazz.getName() + '.'); } } @@ -292,6 +301,7 @@ public static String getLinkByMap(Class clazz, @Nullable String for (String skipInterceptor : bestMatchedLink.skipInterceptors()) { if (skipInterceptor.equals(e.getKey())) { skip = true; + break; } } if (!skip) { @@ -360,6 +370,7 @@ private static List toStringList(@Nonnull TemplateSequenceModel sequence try { item = sequence.get(i); } catch (TemplateModelException e) { + logger.error("Can't get item of Freemarker sequence.", e); throw new NocturneException("Can't get item of Freemarker sequence.", e); } @@ -387,6 +398,7 @@ private static int getSize(@Nonnull TemplateSequenceModel sequence) { try { return sequence.size(); } catch (TemplateModelException e) { + logger.error("Can't get size of Freemarker sequence.", e); throw new NocturneException("Can't get size of Freemarker sequence.", e); } } @@ -416,6 +428,7 @@ public static String getLinkByMap(String name, @Nullable String linkName, Map clazz = classesByName.get(name); if (clazz == null) { + logger.error("Can't find link for page " + name + '.'); throw new NoSuchLinkException("Can't find link for page " + name + '.'); } else { return getLinkByMap(clazz, linkName, params); @@ -462,6 +475,7 @@ private static Map convertArrayToMap(Object... params) { } if (paramCount % 2 != 0) { + logger.error("Params should contain even number of elements."); throw new IllegalArgumentException("Params should contain even number of elements."); } @@ -480,7 +494,7 @@ private static Map convertArrayToMap(Object... params) { * @throws NoSuchLinkException if no such link exists */ public static String getLink(Class pageClass) { - return getLinkByMap(pageClass, null, Collections.emptyMap()); + return getLinkByMap(pageClass, null, Collections.emptyMap()); } /** @@ -524,6 +538,7 @@ public static LinkMatchResult match(String link) { } if (!link.startsWith("/")) { + logger.error("Link \"" + link + "\" doesn't start with '/'."); throw new IllegalArgumentException("Link \"" + link + "\" doesn't start with '/'."); } @@ -559,6 +574,7 @@ public static LinkMatchResult match(String link) { private static Map match(String[] linkTokens, String linkText) { List sections = sectionsByLinkText.get(linkText); if (sections == null) { + logger.error("Can't find sections for linkText=\"" + linkText + "\"."); throw new NocturneException("Can't find sections for linkText=\"" + linkText + "\"."); } @@ -603,6 +619,8 @@ public NoSuchLinkException(String message) { private static List parseLinkToLinkSections(String linkText) { if (linkText == null || linkText.startsWith("/") || linkText.endsWith("/")) { + logger.error("Page link has illegal format, use links like 'home', 'page/{index}', " + + "'page/{index(long,positive):1,2,3}', 'section/{name(string,!blank):!a,b,c}'."); throw new ConfigurationException("Page link has illegal format, use links like 'home', 'page/{index}', " + "'page/{index(long,positive):1,2,3}', 'section/{name(string,!blank):!a,b,c}'." ); @@ -755,6 +773,7 @@ public boolean isSuitable(String value) { private void ensureValueSection(String fieldName) { if (parameter) { + logger.error("Can't read field '" + fieldName + "' of non-value section '" + section + "'."); throw new IllegalStateException(String.format( "Can't read field '%s' of non-value section '%s'.", fieldName, section )); @@ -763,6 +782,7 @@ private void ensureValueSection(String fieldName) { private void ensureParameterSection(String fieldName) { if (!parameter) { + logger.error("Can't read field '" + fieldName + "' of non-parameter section '" + section + "'."); throw new IllegalStateException(String.format( "Can't read field '%s' of non-parameter section '%s'.", fieldName, section )); @@ -988,6 +1008,8 @@ public boolean isSuitable(String value) { } }; } else { + logger.error("Link section '" + section + "' contains unsupported parameter restriction '" + + restrictionRule + "'."); throw new ConfigurationException(String.format( "Link section '%s' contains unsupported parameter restriction '%s'.", section, restrictionRule @@ -1006,13 +1028,15 @@ public static void addInterceptor(String name, Interceptor interceptor) { ensureInterceptorName(name); if (interceptor == null) { - throw new IllegalArgumentException("Argument \'interceptor\' is \'null\'."); + logger.error("Argument 'interceptor' is 'null'."); + throw new IllegalArgumentException("Argument 'interceptor' is 'null'."); } interceptorSemaphore.acquireUninterruptibly(INTERCEPTOR_MAX_PERMIT_COUNT); try { if (interceptorByNameMap.containsKey(name)) { - throw new IllegalStateException("Interceptor with name \'" + name + "\' already added."); + logger.error("Interceptor with name '" + name + "' already added."); + throw new IllegalStateException("Interceptor with name '" + name + "' already added."); } interceptorByNameMap.put(name, interceptor); } finally { @@ -1055,7 +1079,8 @@ public static boolean hasInterceptor(String name) { private static void ensureInterceptorName(String name) { if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Argument \'name\' is \'null\' or empty."); + logger.error("Argument 'name' is 'null' or empty."); + throw new IllegalArgumentException("Argument 'name' is 'null' or empty."); } } diff --git a/code/src/main/java/org/nocturne/main/ActionMap.java b/code/src/main/java/org/nocturne/main/ActionMap.java index e6abefb..448552e 100644 --- a/code/src/main/java/org/nocturne/main/ActionMap.java +++ b/code/src/main/java/org/nocturne/main/ActionMap.java @@ -24,6 +24,8 @@ * @author Mike Mirzayanov */ class ActionMap { + private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ActionMap.class); + /* Default action has empty key "". */ private final Map actions = new ConcurrentHashMap<>(); @@ -55,6 +57,8 @@ class ActionMap { private void processMethodAsDefault(FastClass clazz, Method method) { if (!actions.containsKey("") && "action".equals(method.getName()) && method.getParameterTypes().length == 0) { if (method.getReturnType() != void.class) { + logger.error("Default action method [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return void."); throw new ConfigurationException("Default action method [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return void."); } @@ -63,6 +67,8 @@ private void processMethodAsDefault(FastClass clazz, Method method) { if (!validators.containsKey("") && "validate".equals(method.getName()) && method.getParameterTypes().length == 0) { if (method.getReturnType() != boolean.class) { + logger.error("Default validation method [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return boolean."); throw new ConfigurationException("Default validation method [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return boolean."); } @@ -71,6 +77,8 @@ private void processMethodAsDefault(FastClass clazz, Method method) { if (!invalids.containsKey("") && "invalid".equals(method.getName()) && method.getParameterTypes().length == 0) { if (method.getReturnType() != void.class) { + logger.error("Default invalid method [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return void."); throw new ConfigurationException("Default invalid method [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return void."); } @@ -80,6 +88,7 @@ private void processMethodAsDefault(FastClass clazz, Method method) { private static void ensureProperlyAnnotatedParameters(Method method) { if (method.getParameterTypes().length != method.getParameterAnnotations().length) { + logger.error("Expected \"method.getParameterTypes().length != method.getParameterAnnotations().length\"."); throw new NocturneException("Expected \"method.getParameterTypes().length != method.getParameterAnnotations().length\"."); } @@ -94,10 +103,14 @@ private static void ensureProperlyAnnotatedParameters(Method method) { } } if (!hasParameter) { + logger.error("Each parameter of the method " + method.getDeclaringClass().getName() + + '#' + method.getName() + " should be annotated with @Parameter."); throw new ConfigurationException("Each parameter of the method " + method.getDeclaringClass().getName() + '#' + method.getName() + " should be annotated with @Parameter."); } if (!hasNamedParameter) { + logger.error("Each @Parameter in the method " + method.getDeclaringClass().getName() + + '#' + method.getName() + " should have name."); throw new ConfigurationException("Each @Parameter in the method " + method.getDeclaringClass().getName() + '#' + method.getName() + " should have name."); } @@ -109,6 +122,8 @@ private void processMethod(FastClass clazz, Method method) { if (action != null) { if (actions.containsKey(action.value())) { + logger.error("There are two or more methods for " + + clazz.getName() + " marked with @Action[" + action.value() + "]."); throw new ConfigurationException("There are two or more methods for " + clazz.getName() + " marked with @Action[" + action.value() + "]."); } @@ -116,6 +131,8 @@ private void processMethod(FastClass clazz, Method method) { ensureProperlyAnnotatedParameters(method); if (method.getReturnType() != void.class) { + logger.error("Method with annotation @Action [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return void."); throw new ConfigurationException("Method with annotation @Action [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return void."); } @@ -127,6 +144,8 @@ private void processMethod(FastClass clazz, Method method) { if (validate != null) { if (validators.containsKey(validate.value())) { + logger.error("There are two or more methods for " + + clazz.getName() + " marked with @Validate[" + validate.value() + "]."); throw new ConfigurationException("There are two or more methods for " + clazz.getName() + " marked with @Validate[" + validate.value() + "]."); } @@ -134,6 +153,8 @@ private void processMethod(FastClass clazz, Method method) { ensureProperlyAnnotatedParameters(method); if (method.getReturnType() != boolean.class) { + logger.error("Method with annotation @Validate [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return boolean."); throw new ConfigurationException("Method with annotation @Validate [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return boolean."); } @@ -145,6 +166,8 @@ private void processMethod(FastClass clazz, Method method) { if (invalid != null) { if (invalids.containsKey(invalid.value())) { + logger.error("There are two or more methods for " + + clazz.getName() + " marked with @Invalid[" + invalid.value() + "]."); throw new ConfigurationException("There are two or more methods for " + clazz.getName() + " marked with @Invalid[" + invalid.value() + "]."); } @@ -152,6 +175,8 @@ private void processMethod(FastClass clazz, Method method) { ensureProperlyAnnotatedParameters(method); if (method.getReturnType() != void.class) { + logger.error("Method with annotation @Invalid [name=" + method.getName() + ", " + + "class=" + clazz.getName() + "] should return void."); throw new ConfigurationException("Method with annotation @Invalid [name=" + method.getName() + ", " + "class=" + clazz.getName() + "] should return void."); } diff --git a/code/src/main/java/org/nocturne/main/ApplicationContext.java b/code/src/main/java/org/nocturne/main/ApplicationContext.java index f8a3600..6374a7a 100644 --- a/code/src/main/java/org/nocturne/main/ApplicationContext.java +++ b/code/src/main/java/org/nocturne/main/ApplicationContext.java @@ -47,6 +47,8 @@ */ @SuppressWarnings({"WeakerAccess", "unused"}) public class ApplicationContext { + private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(ApplicationContext.class); + /** * The only singleton instance. */ @@ -698,6 +700,7 @@ void setReloadingClassLoader(ClassLoader loader) { */ public void addReloadingClassPath(File dir) { if (!dir.isDirectory()) { + logger.error("Path " + dir.getName() + " expected to be a directory."); throw new ConfigurationException("Path " + dir.getName() + " expected to be a directory."); } reloadingClassPaths.add(dir); @@ -707,6 +710,7 @@ public void addReloadingClassPath(File dir) { try { ReflectionUtil.invoke(context, "addReloadingClassPath", dir); } catch (ReflectionException e) { + logger.error("Can't call addReloadingClassPath for ReloadingContext.", e); throw new NocturneException("Can't call addReloadingClassPath for ReloadingContext.", e); } } else { @@ -781,6 +785,7 @@ private void initializeCaptions() { Class clazz = (Class) getClass().getClassLoader().loadClass(captionsImplClass); captions = injector.getInstance(clazz); } catch (ClassNotFoundException e) { + logger.error("Class " + captionsImplClass + " not found.", e); throw new ConfigurationException("Class " + captionsImplClass + " should implement Captions.", e); } finally { lock.unlock(); @@ -905,6 +910,7 @@ private static final class RequestContext { private RequestContext(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response) { if ((request == null) ^ (response == null)) { + logger.error("It is not possible case '(request == null) ^ (response == null)'."); throw new IllegalArgumentException("It is not possible case '(request == null) ^ (response == null)'."); } diff --git a/code/src/main/java/org/nocturne/main/ApplicationContextLoader.java b/code/src/main/java/org/nocturne/main/ApplicationContextLoader.java index 836a866..c36d9e4 100644 --- a/code/src/main/java/org/nocturne/main/ApplicationContextLoader.java +++ b/code/src/main/java/org/nocturne/main/ApplicationContextLoader.java @@ -124,6 +124,8 @@ private static void setupAllowedLanguages() { for (String token : tokens) { if (!token.isEmpty()) { if (token.length() != 2) { + logger.error("nocturne.allowed-languages should contain the " + + "list of 2-letters language codes separated with comma."); throw new ConfigurationException("nocturne.allowed-languages should contain the " + "list of 2-letters language codes separated with comma."); } @@ -144,6 +146,8 @@ private static void setupCountryToLanguage() { for (String token : tokens) { if (!token.isEmpty()) { if (!COUNTRIES_TO_LANGUAGE_PATTERN.matcher(token).matches()) { + logger.error("nocturne.countries-to-language should have a form like " + + "\"RU,BY:ru;EN,GB,US,CA:en\"."); throw new ConfigurationException("nocturne.countries-to-language should have a form like " + "\"RU,BY:ru;EN,GB,US,CA:en\"."); } @@ -182,6 +186,7 @@ private static void setupDebugCaptionsDir() { String dir = properties.getProperty("nocturne.debug-captions-dir"); if (dir != null && !dir.isEmpty()) { if (!new File(dir).isDirectory() && ApplicationContext.getInstance().isDebug()) { + logger.error("nocturne.debug-captions-dir property should be a directory."); throw new ConfigurationException("nocturne.debug-captions-dir property should be a directory."); } ApplicationContext.getInstance().setDebugCaptionsDir(dir); @@ -194,6 +199,7 @@ private static void setupDefaultLocale() { String language = properties.getProperty("nocturne.default-language"); if (language != null && !language.isEmpty()) { if (language.length() != 2) { + logger.error("Language is expected to have exactly two letters."); throw new ConfigurationException("Language is expected to have exactly two letters."); } ApplicationContext.getInstance().setDefaultLocale(language); @@ -205,10 +211,12 @@ private static void setupRequestRouter() { if (properties.containsKey("nocturne.request-router")) { String resolver = properties.getProperty("nocturne.request-router"); if (resolver == null || resolver.isEmpty()) { + logger.error("Parameter nocturne.request-router can't be empty."); throw new ConfigurationException("Parameter nocturne.request-router can't be empty."); } ApplicationContext.getInstance().setRequestRouter(resolver); } else { + logger.error("Missed parameter nocturne.request-router."); throw new ConfigurationException("Missed parameter nocturne.request-router."); } } @@ -255,6 +263,7 @@ private static void setupSkipRegex() { try { ApplicationContext.getInstance().setSkipRegex(Pattern.compile(regex)); } catch (PatternSyntaxException e) { + logger.error("Parameter nocturne.skip-regex contains invalid pattern.", e); throw new ConfigurationException("Parameter nocturne.skip-regex contains invalid pattern.", e); } } @@ -291,6 +300,8 @@ private static void setupReloadingClassPaths() { if (dir != null && !dir.isEmpty()) { File file = new File(dir); if (!file.isDirectory() && ApplicationContext.getInstance().isDebug()) { + logger.error("Each item in nocturne.reloading-class-paths should be a directory," + + " but " + file + " is not."); throw new ConfigurationException("Each item in nocturne.reloading-class-paths should be a directory," + " but " + file + " is not."); } @@ -307,10 +318,12 @@ private static void setupTemplates() { try { int templatesUpdateDelay = Integer.parseInt(properties.getProperty("nocturne.templates-update-delay")); if (templatesUpdateDelay < 0 || templatesUpdateDelay > 86400) { + logger.error("Parameter nocturne.templates-update-delay should be non-negative integer not greater than 86400."); throw new ConfigurationException("Parameter nocturne.templates-update-delay should be non-negative integer not greater than 86400."); } ApplicationContext.getInstance().setTemplatesUpdateDelay(templatesUpdateDelay); } catch (NumberFormatException e) { + logger.error("Parameter nocturne.templates-update-delay should be integer.", e); throw new ConfigurationException("Parameter nocturne.templates-update-delay should be integer.", e); } } @@ -322,6 +335,7 @@ private static void setupTemplates() { for (String templatePath : templatePaths) { if (templatePath.isEmpty()) { + logger.error("Item of parameter nocturne.template-paths can't be empty."); throw new ConfigurationException("Item of parameter nocturne.template-paths can't be empty."); } } @@ -331,10 +345,12 @@ private static void setupTemplates() { String templatesPath = StringUtils.trimToEmpty(properties.getProperty("nocturne.templates-path")); if (templatesPath.isEmpty()) { + logger.error("Parameter nocturne.templates-path can't be empty."); throw new ConfigurationException("Parameter nocturne.templates-path can't be empty."); } ApplicationContext.getInstance().setTemplatePaths(new String[]{templatesPath}); } else { + logger.error("Missing parameter nocturne.template-paths."); throw new ConfigurationException("Missing parameter nocturne.template-paths."); } @@ -348,6 +364,7 @@ private static void setupTemplates() { if (properties.containsKey("nocturne.use-component-templates")) { String useComponentTemplates = properties.getProperty("nocturne.use-component-templates"); if (!"false".equals(useComponentTemplates) && !"true".equals(useComponentTemplates)) { + logger.error("Parameter nocturne.use-component-templates expected to be 'false' or 'true'."); throw new ConfigurationException("Parameter nocturne.use-component-templates expected to be 'false' or 'true'."); } boolean use = "true".equals(useComponentTemplates); @@ -360,6 +377,7 @@ private static void setupTemplates() { if (componentTemplatesLessCommonsFile.isFile()) { ApplicationContext.getInstance().setComponentTemplatesLessCommonsFile(componentTemplatesLessCommonsFile); } else { + logger.error("Parameter nocturne.component-templates-less-commons-file is expected to be a file."); throw new ConfigurationException("Parameter nocturne.component-templates-less-commons-file is expected to be a file."); } } @@ -433,6 +451,7 @@ private static void setupInjector() { try { module.setModule(getApplicationModule(guiceModuleClassName)); } catch (Exception e) { + logger.error("Can't load application Guice module.", e); throw new ConfigurationException("Can't load application Guice module.", e); } } @@ -445,10 +464,13 @@ private static void setupInjector() { method.setAccessible(true); method.invoke(ApplicationContext.getInstance(), injector); } catch (NoSuchMethodException e) { + logger.error("Can't find method setInjector.", e); throw new NocturneException("Can't find method setInjector.", e); } catch (InvocationTargetException e) { + logger.error("InvocationTargetException", e); throw new NocturneException("InvocationTargetException", e); } catch (IllegalAccessException e) { + logger.error("IllegalAccessException", e); throw new NocturneException("IllegalAccessException", e); } } else { @@ -509,9 +531,11 @@ private static void runModuleStartups() { runnable = (Runnable) ApplicationContext.getInstance().getInjector().getInstance( ApplicationContext.class.getClassLoader().loadClass(startupClassName)); } catch (ClassCastException e) { + logger.error("Startup class " + startupClassName + " must implement Runnable.", e); throw new ModuleInitializationException("Startup class " + startupClassName + " must implement Runnable.", e); } catch (ClassNotFoundException e) { + logger.error("Can't load startup class be name " + startupClassName + '.', e); throw new ModuleInitializationException("Can't load startup class be name " + startupClassName + '.', e); } @@ -540,10 +564,10 @@ static void shutdown() { } static { - try (InputStream inputStream = ApplicationContextLoader.class.getResourceAsStream(Constants.CONFIGURATION_FILE)) { properties.load(inputStream); } catch (IOException e) { + logger.error("Can't load resource file " + Constants.CONFIGURATION_FILE + '.', e); throw new ConfigurationException("Can't load resource file " + Constants.CONFIGURATION_FILE + '.', e); } } diff --git a/code/src/main/java/org/nocturne/main/PageLoader.java b/code/src/main/java/org/nocturne/main/PageLoader.java index 54a17c5..86ffa08 100644 --- a/code/src/main/java/org/nocturne/main/PageLoader.java +++ b/code/src/main/java/org/nocturne/main/PageLoader.java @@ -41,10 +41,12 @@ void initialize() { ApplicationContext.getInstance().getRequestRouter() ).getConstructor().newInstance(); } catch (NoSuchMethodException e) { + logger.error( + "Application page class name resolver does not have default constructor.", e); throw new ConfigurationException( - "Application page class name resolver does not have default constructor.", e - ); + "Application page class name resolver does not have default constructor.", e); } catch (Exception e) { + logger.error("Can't load application page class name resolver.", e); throw new ConfigurationException("Can't load application page class name resolver.", e); } } @@ -106,6 +108,7 @@ public Page loadPage(String pageClassName) { Class pageClass = (Class) PageLoader.class.getClassLoader().loadClass(pageClassName); return ApplicationContext.getInstance().getInjector().getInstance(pageClass); } catch (Exception e) { + logger.error("Can't load page " + pageClassName + '.', e); throw new ConfigurationException("Can't load page " + pageClassName + '.', e); } } diff --git a/code/src/main/java/org/nocturne/main/ParametersInjector.java b/code/src/main/java/org/nocturne/main/ParametersInjector.java index cb3d617..75cc82f 100644 --- a/code/src/main/java/org/nocturne/main/ParametersInjector.java +++ b/code/src/main/java/org/nocturne/main/ParametersInjector.java @@ -5,6 +5,7 @@ import com.google.common.base.Preconditions; import net.sf.cglib.reflect.FastMethod; +import org.apache.log4j.Logger; import org.jetbrains.annotations.Contract; import org.nocturne.annotation.Parameter; import org.nocturne.exception.ConfigurationException; @@ -35,6 +36,8 @@ */ @SuppressWarnings("WeakerAccess") public class ParametersInjector { + private static final Logger logger = Logger.getLogger(ParametersInjector.class); + private static final Pattern INTEGRAL_VALUE_PATTERN = Pattern.compile("0|(-?[1-9][0-9]*)"); private static final Pattern REAL_VALUE_PATTERN = Pattern.compile("(0|(-?[1-9][0-9]*))((\\.[0-9]+)?)"); @@ -87,6 +90,7 @@ Object[] setupParameters(HttpServletRequest request, FastMethod method) { Annotation[][] parameterAnnotations = method.getJavaMethod().getParameterAnnotations(); if (parameterTypes.length != parameterAnnotations.length) { + logger.error("Expected the same number of parameters and annotations."); throw new NocturneException("Expected the same number of parameters and annotations."); } @@ -101,10 +105,14 @@ Object[] setupParameters(HttpServletRequest request, FastMethod method) { } } if (parameter == null) { + logger.error("Each parameter of the method " + method.getDeclaringClass().getName() + + '#' + method.getName() + " should be annotated with @Parameter."); throw new ConfigurationException("Each parameter of the method " + method.getDeclaringClass().getName() + '#' + method.getName() + " should be annotated with @Parameter."); } if (StringUtil.isEmpty(parameter.name())) { + logger.error("Each @Parameter in the method " + method.getDeclaringClass().getName() + + '#' + method.getName() + " should have name."); throw new ConfigurationException("Each @Parameter in the method " + method.getDeclaringClass().getName() + '#' + method.getName() + " should have name."); } @@ -364,10 +372,12 @@ private void setFieldValue(InjectField field, @Nullable Object assign) { try { field.field.set(component, assign); } catch (IllegalAccessException e) { - throw new IllegalArgumentException(String.format( + String message = String.format( "Don't have access to set field %s of %s.", field.field.getName(), field.field.getDeclaringClass().getName() - ), e); + ); + logger.error(message, e); + throw new IllegalArgumentException(message, e); } } } diff --git a/code/src/main/java/org/nocturne/main/ReloadingContext.java b/code/src/main/java/org/nocturne/main/ReloadingContext.java index 0ac1e0d..36bdd4a 100644 --- a/code/src/main/java/org/nocturne/main/ReloadingContext.java +++ b/code/src/main/java/org/nocturne/main/ReloadingContext.java @@ -3,6 +3,7 @@ */ package org.nocturne.main; +import org.apache.log4j.Logger; import org.nocturne.exception.ConfigurationException; import java.io.File; @@ -16,6 +17,8 @@ */ @SuppressWarnings({"unused", "WeakerAccess"}) public class ReloadingContext { + private static final Logger logger = Logger.getLogger(ReloadingContext.class); + private static final ReloadingContext INSTANCE = new ReloadingContext(); private static final AtomicBoolean initialized = new AtomicBoolean(false); @@ -101,6 +104,7 @@ void setClassReloadingExceptions(List classReloadingExceptions) { void addReloadingClassPath(File dir) { if (!dir.isDirectory()) { + logger.error("Path " + dir.getName() + " expected to be a directory."); throw new ConfigurationException("Path " + dir.getName() + " expected to be a directory."); } if (!reloadingClassPaths.contains(dir)) { diff --git a/code/src/main/java/org/nocturne/main/ReloadingContextLoader.java b/code/src/main/java/org/nocturne/main/ReloadingContextLoader.java index b10966f..09a7c81 100644 --- a/code/src/main/java/org/nocturne/main/ReloadingContextLoader.java +++ b/code/src/main/java/org/nocturne/main/ReloadingContextLoader.java @@ -3,6 +3,7 @@ */ package org.nocturne.main; +import org.apache.log4j.Logger; import org.nocturne.exception.ConfigurationException; import org.nocturne.prometheus.Prometheus; @@ -19,6 +20,8 @@ * @author Mike Mirzayanov */ class ReloadingContextLoader { + private static final Logger logger = Logger.getLogger(ReloadingContextLoader.class); + private static final Properties properties = new Properties(); static void run() { @@ -38,10 +41,12 @@ private static void setupTemplates() { try { int templatesUpdateDelay = Integer.parseInt(properties.getProperty("nocturne.templates-update-delay")); if (templatesUpdateDelay < 0 || templatesUpdateDelay > 86400) { + logger.error("Parameter nocturne.templates-update-delay should be non-negative integer not greater than 86400."); throw new ConfigurationException("Parameter nocturne.templates-update-delay should be non-negative integer not greater than 86400."); } ReloadingContext.getInstance().setTemplatesUpdateDelay(templatesUpdateDelay); } catch (NumberFormatException e) { + logger.error("Parameter nocturne.templates-update-delay should be integer."); throw new ConfigurationException("Parameter nocturne.templates-update-delay should be integer."); } } @@ -72,6 +77,7 @@ private static void setupSkipRegex() { try { ReloadingContext.getInstance().setSkipRegex(Pattern.compile(regex)); } catch (PatternSyntaxException e) { + logger.error("Parameter nocturne.skip-regex contains invalid pattern."); throw new ConfigurationException("Parameter nocturne.skip-regex contains invalid pattern."); } } @@ -105,6 +111,8 @@ private static void setupReloadingClassPaths() { if (!dir.isEmpty()) { File file = new File(dir); if (!file.isDirectory() && ReloadingContext.getInstance().isDebug()) { + logger.error("Each item in nocturne.reloading-class-paths should be a directory," + + " but '" + file + "' isn't."); throw new ConfigurationException("Each item in nocturne.reloading-class-paths should be a directory," + " but '" + file + "' isn't."); } @@ -123,6 +131,7 @@ private static void setupDebug() { try { debug = Boolean.parseBoolean(properties.getProperty("nocturne.debug")); } catch (NullPointerException e) { + logger.error("Can't cast nocturne.debug to boolean."); throw new ConfigurationException("Can't cast nocturne.debug to boolean."); } } @@ -135,6 +144,7 @@ private static void setupDebug() { try (InputStream inputStream = ApplicationContextLoader.class.getResourceAsStream(Constants.CONFIGURATION_FILE)) { properties.load(inputStream); } catch (IOException e) { + logger.error("Can't load resource file " + Constants.CONFIGURATION_FILE + '.', e); throw new ConfigurationException("Can't load resource file " + Constants.CONFIGURATION_FILE + '.', e); } } diff --git a/code/src/main/java/org/nocturne/module/PreprocessFreemarkerFileTemplateLoader.java b/code/src/main/java/org/nocturne/module/PreprocessFreemarkerFileTemplateLoader.java index 995fb94..e76c01f 100644 --- a/code/src/main/java/org/nocturne/module/PreprocessFreemarkerFileTemplateLoader.java +++ b/code/src/main/java/org/nocturne/module/PreprocessFreemarkerFileTemplateLoader.java @@ -31,6 +31,9 @@ */ @SuppressWarnings({"WeakerAccess", "unused"}) public class PreprocessFreemarkerFileTemplateLoader extends MultiTemplateLoader { + private static final org.apache.log4j.Logger logger + = org.apache.log4j.Logger.getLogger(PreprocessFreemarkerFileTemplateLoader.class); + private static final ConcurrentMap templateSourceByName = new ConcurrentHashMap<>(); private final int templateDirCount; @@ -42,6 +45,7 @@ public PreprocessFreemarkerFileTemplateLoader(File... templateDirs) throws IOExc private static TemplateLoader[] getTemplateLoaders(File[] templateDirs) throws IOException { int templateDirCount = templateDirs.length; if (templateDirCount <= 0) { + logger.error("Please specify at least one template directory."); throw new ConfigurationException("Please specify at least one template directory."); } @@ -127,6 +131,7 @@ private static void processCaptions(StringBuilder sb) { String content = sb.substring(index + 2, closeIndex); if (content.startsWith("!")) { + logger.error("{{!...}} syntax is no more supported."); throw new UnsupportedOperationException("{{!...}} syntax is no more supported."); } diff --git a/code/src/main/java/org/nocturne/reset/FieldsResetter.java b/code/src/main/java/org/nocturne/reset/FieldsResetter.java index 2420fdc..eb500d0 100644 --- a/code/src/main/java/org/nocturne/reset/FieldsResetter.java +++ b/code/src/main/java/org/nocturne/reset/FieldsResetter.java @@ -17,6 +17,8 @@ * @author Mike Mirzayanov */ abstract class FieldsResetter { + private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(FieldsResetter.class); + private static final Map, Object> PRIMITIVES_DEFAULT_VALUES = new ConcurrentHashMap<>(); private static final ConcurrentMap RESET_ANNOTATIONS_CACHE = new ConcurrentHashMap<>(); private static final ConcurrentMap PERSIST_ANNOTATIONS_CACHE = new ConcurrentHashMap<>(); @@ -144,6 +146,7 @@ private void resetPrimitiveField(Field field) { private static ResetStrategy getStrategy( ResetStrategy defaultStrategy, boolean hasReset, boolean hasPersist, String name) { if (hasPersist && hasReset) { + logger.error("It is impossible to use Reset and Persist at the same time [name=" + name + "]."); throw new ConfigurationException("It is impossible to use " + "Reset and Persist at the same time [name=" + name + "]."); }