diff --git a/app/src/main/java/net/moasdawiki/app/CalendarSyncAdapter.java b/app/src/main/java/net/moasdawiki/app/CalendarSyncAdapter.java index d6e8033..8269e45 100644 --- a/app/src/main/java/net/moasdawiki/app/CalendarSyncAdapter.java +++ b/app/src/main/java/net/moasdawiki/app/CalendarSyncAdapter.java @@ -43,9 +43,7 @@ import androidx.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; -import net.moasdawiki.plugin.Plugin; -import net.moasdawiki.plugin.PluginService; -import net.moasdawiki.plugin.TerminPlugin; +import net.moasdawiki.service.transform.TerminTransformer; import net.moasdawiki.util.PathUtils; import org.jetbrains.annotations.NotNull; @@ -87,7 +85,7 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter { @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { Log.d(TAG, "Begin of onPerformSync()"); - List events = getWikiEvents(); + List events = getWikiEvents(); String calendarId = createCalendar(); if (calendarId != null) { deleteAllEvents(calendarId); @@ -106,21 +104,15 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter { * Imports all events on Wiki pages to the Android calendar. */ @NotNull - private List getWikiEvents() { + private List getWikiEvents() { Log.d(TAG, "Reading Wiki events"); WikiEngineApplication app = (WikiEngineApplication) getContext(); - PluginService pluginService = app.getServiceLocator().getPluginService(); - TerminPlugin terminPlugin = null; - for (Plugin plugin : pluginService.getPlugins()) { - if (plugin instanceof TerminPlugin) { - terminPlugin = (TerminPlugin) plugin; - } - } - if (terminPlugin == null) { - Log.e(TAG, "TerminPlugin not found, cannot retrieve event list"); + TerminTransformer terminTransformer = app.getTerminTransformer(); + if (terminTransformer == null) { + Log.e(TAG, "TerminTransformer not initialized yet, cannot retrieve event list"); return Collections.emptyList(); } - List events = terminPlugin.getEvents(); + List events = terminTransformer.getEvents(); Log.d(TAG, "Wiki events found: " + events.size()); return events; } @@ -203,14 +195,14 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter { * Adds all events from the event list. The first occurrence is in the current year, the events * are repeated every year. */ - private void addEvents(@NotNull String calendarId, @NotNull List events) { + private void addEvents(@NotNull String calendarId, @NotNull List events) { Log.d(TAG, "Create calendar events"); - for (TerminPlugin.Event event : events) { + for (TerminTransformer.Event event : events) { String title = event.description; if (title == null) { title = PathUtils.extractWebName(event.pagePath); } - String description = getContext().getString(R.string.calendar_date) + ": " + TerminPlugin.formatGermanDate(event.dateFields); + String description = getContext().getString(R.string.calendar_date) + ": " + TerminTransformer.formatGermanDate(event.dateFields); String eventId = addEvent(calendarId, event.dateFields.day, event.dateFields.month, event.dateFields.year, title, description); if (eventId != null) { addReminder(eventId); diff --git a/app/src/main/java/net/moasdawiki/app/Constants.java b/app/src/main/java/net/moasdawiki/app/Constants.java index c100d52..e38cb8e 100644 --- a/app/src/main/java/net/moasdawiki/app/Constants.java +++ b/app/src/main/java/net/moasdawiki/app/Constants.java @@ -20,8 +20,6 @@ package net.moasdawiki.app; /** * Enthält zentrale Konstanten. - * - * @author Herbert Reiter */ public abstract class Constants { public static final String PREFERENCES_SYNC_SERVER_HOST = "sync_server_host"; diff --git a/app/src/main/java/net/moasdawiki/app/MainActivity.java b/app/src/main/java/net/moasdawiki/app/MainActivity.java index 992e927..5ebe116 100644 --- a/app/src/main/java/net/moasdawiki/app/MainActivity.java +++ b/app/src/main/java/net/moasdawiki/app/MainActivity.java @@ -47,17 +47,16 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.view.menu.MenuBuilder; import androidx.preference.PreferenceManager; import net.moasdawiki.base.ServiceException; import net.moasdawiki.base.Settings; -import net.moasdawiki.plugin.Plugin; -import net.moasdawiki.plugin.PluginService; import net.moasdawiki.server.HttpRequest; -import net.moasdawiki.server.HttpResponse; -import net.moasdawiki.service.render.HtmlService; +import net.moasdawiki.server.RequestDispatcher; +import net.moasdawiki.service.HttpResponse; import net.moasdawiki.service.repository.RepositoryService; import net.moasdawiki.util.EscapeUtils; @@ -77,19 +76,16 @@ import java.util.Map; /** * Steuert das Verhalten des Hauptfensters inkl. eingebettetem Browser. - * - * @author Herbert Reiter */ public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final String SERVER_BASE_URL = "http://localhost:1/"; - private Settings settings; private RepositoryService repositoryService; - private PluginService pluginService; - private HtmlService htmlService; + private Settings settings; private SynchronizeWikiClient synchronizeWikiClient; + private RequestDispatcher requestDispatcher; private WebView webview; @@ -102,11 +98,10 @@ public class MainActivity extends AppCompatActivity { // AndroidMainService holen WikiEngineApplication app = (WikiEngineApplication) getApplication(); - settings = app.getServiceLocator().getSettings(); - repositoryService = app.getServiceLocator().getRepositoryService(); - pluginService = app.getServiceLocator().getPluginService(); - htmlService = app.getServiceLocator().getHtmlService(); + repositoryService = app.getRepositoryService(); + settings = app.getSettings(); synchronizeWikiClient = app.getSynchronizeWikiClient(); + requestDispatcher = app.getRequestDispatcher(); // eingebetteten Browser konfigurieren initWebView(); @@ -177,32 +172,20 @@ public class MainActivity extends AppCompatActivity { urlPath = urlPath.substring(0, hashPos); } - // per URL-Mapping das zuständige Plugin aufrufen - HttpResponse response; - Plugin plugin = pluginService.getPluginByUrl(urlPath); - if (plugin != null) { - HttpRequest httpRequest = new HttpRequest(); - httpRequest.clientIP = InetAddress.getLocalHost(); - httpRequest.httpHeader = Collections.emptyMap(); - httpRequest.method = "GET"; - httpRequest.url = urlPath; - httpRequest.urlPath = urlPath; - httpRequest.urlParameters = convertParameters(uri); - httpRequest.httpBody = new byte[0]; - - response = plugin.handleRequest(httpRequest); - if (response == null) { - response = htmlService.generateErrorPage(404, "wiki.plugin.handleRequest.notsupported", plugin.getClass().getName()); - } - } else { - // unbekannte URL - response = htmlService.generateErrorPage(404, "wiki.server.url.unmapped", urlPath); - } + // dispatch URL path + HttpRequest httpRequest = new HttpRequest(); + httpRequest.clientIP = InetAddress.getLocalHost(); + httpRequest.httpHeader = Collections.emptyMap(); + httpRequest.method = "GET"; + httpRequest.url = urlPath; + httpRequest.urlPath = urlPath; + httpRequest.urlParameters = convertParameters(uri); + httpRequest.httpBody = new byte[0]; + HttpResponse response = requestDispatcher.handleRequest(httpRequest); // Antwortdaten einspeisen - InputStream responseData = new ByteArrayInputStream(response.getContent()); - return new WebResourceResponse(response.getContentType(), - "UTF-8", responseData); + InputStream responseData = new ByteArrayInputStream(response.content); + return new WebResourceResponse(response.contentType, "UTF-8", responseData); } catch (IOException e) { e.printStackTrace(); } @@ -256,30 +239,29 @@ public class MainActivity extends AppCompatActivity { // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. - switch (item.getItemId()) { - case R.id.action_synchronize: - synchronizeServer(); - return true; - case R.id.action_startpage: - loadUrl(SERVER_BASE_URL); - return true; - case R.id.action_settings: - showSettingsDialog(); - return true; - case R.id.action_help: - String pagePathHelp = getWikiserverHelpUrl(); - loadUrl(pagePathHelp); - return true; - case R.id.action_about: - showAboutDialog(); - return true; - default: - return super.onOptionsItemSelected(item); + int itemId = item.getItemId(); + if (itemId == R.id.action_synchronize) { + synchronizeServer(); + return true; + } else if (itemId == R.id.action_startpage) { + loadUrl(SERVER_BASE_URL); + return true; + } else if (itemId == R.id.action_settings) { + showSettingsDialog(); + return true; + } else if (itemId == R.id.action_help) { + String pagePathHelp = getWikiserverHelpUrl(); + loadUrl(pagePathHelp); + return true; + } else if (itemId == R.id.action_about) { + showAboutDialog(); + return true; } + return super.onOptionsItemSelected(item); } @Override - public void onRequestPermissionsResult(int requestCode, @NotNull String[] permissions, @NotNull int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Log.d(TAG, "Permission granted by user: requestCode=" + requestCode + ", permissions=" + Arrays.toString(permissions) + ", grantResults=" + Arrays.toString(grantResults)); super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -307,15 +289,15 @@ public class MainActivity extends AppCompatActivity { } } - public void onConfigurationHintClicked(@SuppressWarnings("unused") View view) { + public void onConfigurationHintClicked(View view) { showSettingsDialog(); } - public void onSynchronizeHintClicked(@SuppressWarnings("unused") View view) { + public void onSynchronizeHintClicked(View view) { synchronizeServer(); } - public void onSearch(@SuppressWarnings("unused") View view) { + public void onSearch(View view) { EditText searchInput = findViewById(R.id.search_input); String query = searchInput.getText().toString(); query = query.trim(); @@ -455,8 +437,6 @@ public class MainActivity extends AppCompatActivity { /** * Synchronisiert mit dem Wikiserver in einem separaten Thread. */ - @SuppressLint("StaticFieldLeak") - @SuppressWarnings("NonStaticInnerClassInSecureContext") private class SyncNowTask extends AsyncTask implements SynchronizeWikiClient.ProgressFeedback { @Nullable diff --git a/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java b/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java index 404657a..0c57f74 100644 --- a/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java +++ b/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java @@ -29,20 +29,9 @@ import androidx.preference.PreferenceManager; import net.moasdawiki.base.Logger; import net.moasdawiki.base.ServiceException; import net.moasdawiki.base.Settings; -import net.moasdawiki.plugin.ServiceLocator; -import net.moasdawiki.plugin.sync.AbstractSyncXml; -import net.moasdawiki.plugin.sync.CheckSessionResponseXml; -import net.moasdawiki.plugin.sync.CheckSessionXml; -import net.moasdawiki.plugin.sync.CreateSessionResponseXml; -import net.moasdawiki.plugin.sync.CreateSessionXml; -import net.moasdawiki.plugin.sync.ErrorResponseXml; -import net.moasdawiki.plugin.sync.ListModifiedFilesResponseXml; -import net.moasdawiki.plugin.sync.ListModifiedFilesXml; -import net.moasdawiki.plugin.sync.ReadFileResponseXml; -import net.moasdawiki.plugin.sync.ReadFileXml; -import net.moasdawiki.plugin.sync.SingleFileXml; import net.moasdawiki.service.repository.AnyFile; import net.moasdawiki.service.repository.RepositoryService; +import net.moasdawiki.service.sync.*; import net.moasdawiki.util.DateUtils; import net.moasdawiki.util.xml.XmlGenerator; import net.moasdawiki.util.xml.XmlParser; @@ -67,8 +56,6 @@ import java.util.Enumeration; /** * Sucht einen Wikiserver in Netzwerk und synchronisiert alle Wikidateien * im eigenen Repository.. - * - * @author Herbert Reiter */ public class SynchronizeWikiClient { @@ -85,13 +72,15 @@ public class SynchronizeWikiClient { @NotNull private final RepositoryService repositoryService; @NotNull - private final SecureRandom random = new SecureRandom(); + private final SecureRandom random; - public SynchronizeWikiClient(@NotNull Context mContext, @NotNull ServiceLocator serviceLocator) { + public SynchronizeWikiClient(@NotNull Context mContext, @NotNull Logger logger, @NotNull Settings settings, + @NotNull RepositoryService repositoryService) { this.mContext = mContext; - this.logger = serviceLocator.getLogger(); - this.settings = serviceLocator.getSettings(); - this.repositoryService = serviceLocator.getRepositoryService(); + this.logger = logger; + this.settings = settings; + this.repositoryService = repositoryService; + this.random = new SecureRandom(); } /** diff --git a/app/src/main/java/net/moasdawiki/app/WikiEngineApplication.java b/app/src/main/java/net/moasdawiki/app/WikiEngineApplication.java index 26f4226..617eaf6 100644 --- a/app/src/main/java/net/moasdawiki/app/WikiEngineApplication.java +++ b/app/src/main/java/net/moasdawiki/app/WikiEngineApplication.java @@ -23,58 +23,88 @@ import android.app.Application; import net.moasdawiki.base.Logger; import net.moasdawiki.base.Messages; import net.moasdawiki.base.Settings; -import net.moasdawiki.plugin.PluginService; -import net.moasdawiki.plugin.ServiceLocator; +import net.moasdawiki.server.RequestDispatcher; +import net.moasdawiki.service.handler.EditorHandler; +import net.moasdawiki.service.handler.FileDownloadHandler; +import net.moasdawiki.service.handler.SearchHandler; +import net.moasdawiki.service.handler.ViewPageHandler; import net.moasdawiki.service.render.HtmlService; -import net.moasdawiki.service.repository.FilesystemRepositoryService; import net.moasdawiki.service.repository.RepositoryService; import net.moasdawiki.service.search.SearchService; +import net.moasdawiki.service.transform.IncludePageTransformer; +import net.moasdawiki.service.transform.KontaktseiteTransformer; +import net.moasdawiki.service.transform.TerminTransformer; +import net.moasdawiki.service.transform.TransformWikiPage; +import net.moasdawiki.service.transform.TransformerService; +import net.moasdawiki.service.transform.WikiTagsTransformer; import net.moasdawiki.service.wiki.WikiService; -import net.moasdawiki.service.wiki.WikiServiceImpl; import java.io.File; /** - * Verwaltet den Lebenszyklus der Wiki Engine. Muss außerhalb der Activities erfolgen, weil diese - * z.B. beim Drehen des Bildschirm neu erzeugt werden. + * Main control of the wiki App. * - * @author Herbert Reiter + * Must be run globally for the App, i.e. outside of an activity. */ public class WikiEngineApplication extends Application { + private static final String REPOSITORY_ROOT_PATH_DEFAULT = "repository"; private Logger logger; - private ServiceLocator serviceLocator; + private RepositoryService repositoryService; + private Settings settings; + private Messages messages; + private WikiService wikiService; private SynchronizeWikiClient synchronizeWikiClient; + private TerminTransformer terminTransformer; + private RequestDispatcher requestDispatcher; @Override public void onCreate() { super.onCreate(); logger = new Logger(System.out); - logger.write("MoasdaWiki app starting"); + logger.write("MoasdaWiki App starting"); - File internalStorageRepositoryRoot = new File(getFilesDir(), "repository"); - RepositoryService repositoryService = new FilesystemRepositoryService(logger, internalStorageRepositoryRoot); + File internalStorageRepositoryRoot = new File(getFilesDir(), REPOSITORY_ROOT_PATH_DEFAULT); + + // basic services + repositoryService = new RepositoryService(logger, internalStorageRepositoryRoot); repositoryService.init(); - WikiService wikiService = new WikiServiceImpl(logger, repositoryService); - SearchService searchService = new SearchService(logger, repositoryService, wikiService, true); - Settings settings = new AndroidSettings(logger, repositoryService, AndroidSettings.getConfigFileApp()); - Messages messages = new Messages(logger, settings, repositoryService); - PluginService pluginService = new PluginService(logger, settings); - HtmlService htmlService = new HtmlService(logger, settings, messages, wikiService, pluginService); - serviceLocator = new ServiceLocator(logger, settings, messages, repositoryService, wikiService, htmlService, searchService, pluginService); + settings = new Settings(logger, repositoryService, Settings.getConfigFileServer()); + messages = new Messages(logger, settings, repositoryService); + wikiService = new WikiService(logger, repositoryService); + SearchService searchService = new SearchService(logger, repositoryService, wikiService, false); - pluginService.loadPlugins(serviceLocator); + // App: use SynchronizeWikiClient instead of SynchronizationService + synchronizeWikiClient = new SynchronizeWikiClient(this, logger, settings, repositoryService); - synchronizeWikiClient = new SynchronizeWikiClient(this, serviceLocator); + // transformers + // do not run the SynchronizationPageTransformer + IncludePageTransformer includePageTransformer = new IncludePageTransformer(logger, wikiService); + KontaktseiteTransformer kontaktseiteTransformer = new KontaktseiteTransformer(); + terminTransformer = new TerminTransformer(logger, messages, repositoryService, wikiService); + WikiTagsTransformer wikiTagsTransformer = new WikiTagsTransformer(logger, settings, messages, wikiService); + // list of transformers, the order matters + TransformWikiPage[] transformers = {includePageTransformer, kontaktseiteTransformer, terminTransformer, wikiTagsTransformer}; + TransformerService transformerService = new TransformerService(transformers); + + // more services + HtmlService htmlService = new HtmlService(logger, settings, messages, wikiService, transformerService); + + // HTTP handlers + ViewPageHandler viewPageHandler = new ViewPageHandler(logger, settings, wikiService, htmlService); + SearchHandler searchHandler = new SearchHandler(logger, settings, messages, wikiService, searchService, htmlService); + EditorHandler editorHandler = new EditorHandler(logger, settings, messages, repositoryService, wikiService, transformerService, htmlService); + FileDownloadHandler fileDownloadHandler = new FileDownloadHandler(logger, settings, repositoryService, htmlService); + requestDispatcher = new RequestDispatcher(htmlService, viewPageHandler, + searchHandler, editorHandler, fileDownloadHandler, null); } public void resetServices() { - serviceLocator.getRepositoryService().rebuildCache(); - serviceLocator.getWikiService().reset(); - serviceLocator.getSettings().reset(); - serviceLocator.getMessages().reset(); - serviceLocator.getPluginService().loadPlugins(serviceLocator); + repositoryService.rebuildCache(); + wikiService.reset(); + settings.reset(); + messages.reset(); } @Override @@ -83,11 +113,23 @@ public class WikiEngineApplication extends Application { super.onTerminate(); } - public ServiceLocator getServiceLocator() { - return serviceLocator; + public RepositoryService getRepositoryService() { + return repositoryService; + } + + public Settings getSettings() { + return settings; + } + + public TerminTransformer getTerminTransformer() { + return terminTransformer; } public SynchronizeWikiClient getSynchronizeWikiClient() { return synchronizeWikiClient; } + + public RequestDispatcher getRequestDispatcher() { + return requestDispatcher; + } }