From 63e0ee1fb8038eb6d8f0190cf38c3b3ab2727216 Mon Sep 17 00:00:00 2001 From: zapata Date: Sun, 21 Nov 2004 22:07:12 +0000 Subject: [PATCH] 1.1 restoration --- build.xml | 369 +++--- bundles/admin_en.properties | 15 +- bundles/admin_es.properties | 216 ++-- bundles/admin_eu.properties | 1273 +++++++++----------- bundles/admin_ro.properties | 530 ++++++++ dbscripts/help_arttype.sql | 1 + dbscripts/help_lang.sql | 1 + doc/CODESTRUCTURE | 153 --- doc/CODINGSTYLE | 36 - doc/DC.txt | 128 -- doc/INSTALL.mir | 259 ---- doc/INTERNATIONALIZATION.howto | 53 - doc/KNOWN_BUGS | 24 - doc/LOCALIZER.HOWTO | 20 - doc/LONG.INSTALL.mir | 537 --------- doc/README | 88 -- doc/README.jikes | 5 - doc/TODO.txt | 91 -- doc/UPGRADING.mir | 29 - doc/mission.html | 39 +- etc/bundles/adminlocal.properties | 1 + etc/bundles/open_en.properties | 6 +- etc/config.properties-dist | 138 +-- etc/content-types.properties | 285 ----- etc/extralib/README | 1 + etc/log4j.properties | 2 +- etc/open/comment.template | 132 -- etc/open/comment_done.template | 37 - etc/open/comment_dupe.template | 37 - etc/open/donetranslation.template | 55 + etc/open/editarticle.template | 116 +- etc/open/editcomment.template | 61 +- etc/open/edittranslation.template | 334 +++++ etc/open/error.template | 2 +- etc/open/posting.template | 234 ---- etc/open/posting_done.template | 35 - etc/open/posting_dupe.template | 37 - ...{prepare_mail.template => preparemail.template} | 17 +- etc/open/search_results.template | 2 - etc/open/sessionerror.template | 4 +- etc/open/unsupportedmediatype.template | 7 +- etc/producer/RSS-full.template | 97 ++ etc/producer/RSS.template | 19 +- etc/producer/article.template | 26 +- etc/producer/featurearchive.template | 33 +- etc/producer/languagebar.template | 4 + etc/producer/navigation.template | 18 +- etc/producer/newswirearchive.template | 34 +- etc/producer/producers.xml | 196 ++- etc/producer/radicalendar.template | 5 + etc/producer/routines.template | 154 +-- etc/producer/startpage.template | 80 +- etc/producer/topicpage.template | 66 +- etc/scripts/bundletool.sh | 20 + etc/scripts/produce.sh | 3 + etc/scripts/reload.sh | 3 + etc/server.xml | 10 - lib/README.txt | 36 +- lib/commons-dbcp-1.1.jar | Bin 0 -> 100776 bytes lib/commons-fileupload-1.0-beta-1.jar | Bin 15807 -> 0 bytes lib/commons-fileupload-1.0.jar | Bin 0 -> 22379 bytes lib/commons-httpclient-2.0.jar | Bin 0 -> 222618 bytes lib/commons-pool-1.1.jar | Bin 0 -> 39523 bytes lib/poolman.jar | Bin 81214 -> 0 bytes lib/postgresql-72jdbc2.jar | Bin 116204 -> 0 bytes lib/postgresql-74jdbc2.jar | Bin 0 -> 185265 bytes lib/strutsmesg.jar | Bin 18667 -> 0 bytes lib/xmlrpc-1.2-b1.jar | Bin 0 -> 108476 bytes {etc => meta}/web.xml | 39 - perms.sh-dist | 2 +- scripts/produce.sh | 3 - scripts/search.pl | 101 -- source/Mir.java | 103 +- source/OpenMir.java | 11 +- source/default.properties | 97 +- source/mir/bundle/BasicBundleFactory.java | 86 ++ source/mir/bundle/Bundle.java | 36 + source/mir/bundle/BundleFactory.java | 42 + source/mir/bundle/BundleLoader.java | 52 + source/mir/bundle/CascadingBundleFactory.java | 70 ++ source/mir/bundle/PropertiesBundle.java | 84 ++ source/mir/bundle/PropertiesFileBundleLoader.java | 67 ++ source/mir/config/MirPropertiesConfiguration.java | 138 +-- source/mir/entity/AbstractEntity.java | 16 +- source/mir/entity/EntityList.java | 83 +- source/mir/entity/adapter/EntityListAdapter.java | 4 +- .../mir/generator/CompositeGeneratorLibrary.java | 10 +- source/mir/generator/FreemarkerGenerator.java | 48 +- source/mir/generator/Generator.java | 15 +- source/mir/generator/GeneratorHelper.java | 54 +- .../mir/generator/GeneratorLibraryRepository.java | 51 +- source/mir/generator/TALGenerator.java | 65 +- source/mir/generator/VelocityGenerator.java | 92 +- source/mir/generator/tal/CachingFileLoader.java | 4 +- source/mir/generator/tal/MirExpressionParser.java | 8 + .../tal/SimpleTemplateNodeLibraryRegistry.java | 59 + source/mir/generator/tal/TALTemplateEngine.java | 74 +- source/mir/generator/tal/TALTemplateParser.java | 66 +- source/mir/generator/tal/TALTest.java | 63 +- .../tal/interfaces/TALExpressionParser.java | 14 +- .../tal/template/CompositeTemplateNode.java | 44 +- ...deLibrary.java => CoreTemplateNodeLibrary.java} | 131 +- .../tal/template/MacroTemplateNodeLibrary.java | 207 ++++ .../tal/template/PlainTextTemplateNode.java | 41 +- .../template/{TALTemplate.java => Template.java} | 28 +- .../generator/tal/template/TemplateLibrary.java | 41 + .../mir/generator/tal/template/TemplateNode.java | 17 +- ...teNodeLibrary.java => TemplateNodeLibrary.java} | 13 +- .../tal/template/TemplateNodeLibraryRegistry.java | 35 + .../tal/template/TemplateProcessingException.java | 4 + source/mir/log/Logger.java | 16 +- source/mir/log/{Log.java => LoggerEngine.java} | 45 +- .../mir/log/{TestFramework.java => LoggerExc.java} | 27 +- source/mir/log/LoggerFailure.java | 43 + source/mir/log/LoggerWrapper.java | 24 +- source/mir/log/log4j/LoggerImpl.java | 48 +- source/mir/media/MediaHandler.java | 79 +- source/mir/misc/FileUtil.java | 32 +- source/mir/module/AbstractModule.java | 7 +- ...leProducerNode.java => BundleProducerNode.java} | 62 +- source/mir/producer/CompositeProducerNode.java | 18 +- source/mir/producer/DirCopyingProducerNode.java | 22 +- .../mir/producer/EntityBatchingProducerNode.java | 23 +- .../producer/EntityEnumeratingProducerNode.java | 24 +- source/mir/producer/EntityListProducerNode.java | 86 +- ...erNode.java => ExecuteProgramProducerNode.java} | 42 +- source/mir/producer/ExternalDbProducerNode.java | 120 ++ .../mir/producer/FileDateSettingProducerNode.java | 17 +- source/mir/producer/GeneratingProducerNode.java | 6 +- source/mir/producer/ProducerFactory.java | 18 +- source/mir/producer/ProducerNode.java | 22 +- source/mir/producer/RSSProducerNode.java | 32 +- .../reader/DefaultProducerNodeBuilders.java | 240 ++-- .../mir/producer/reader/ProducerConfigReader.java | 25 +- .../producer/reader/ScriptedProducerFactory.java | 4 +- source/mir/rss/RSS091Reader.java | 44 +- source/mir/rss/RSSAggregator.java | 4 +- source/mir/rss/RSSData.java | 6 +- source/mir/rss/RSSReader.java | 48 +- source/mir/servlet/AbstractServlet.java | 76 +- source/mir/servlet/ServletModule.java | 170 +-- source/mir/session/CommonsUploadedFileAdapter.java | 25 +- source/mir/session/HTTPAdapters.java | 74 +- source/mir/session/Request.java | 1 + source/mir/session/UploadedFile.java | 31 +- source/mir/storage/Database.java | 544 +++++---- source/mir/storage/StorageObject.java | 15 +- source/mir/storage/store/ObjectStore.java | 48 +- source/mir/storage/store/StoreUtil.java | 16 +- source/mir/util/CachingRewindableIterator.java | 17 +- source/mir/util/ExceptionFunctions.java | 13 +- source/mir/util/FileFunctions.java | 78 +- source/mir/util/GeneratorDateTimeFunctions.java | 6 +- source/mir/util/GeneratorFormatAdapters.java | 8 +- source/mir/util/GeneratorHTMLFunctions.java | 113 -- source/mir/util/GeneratorIntegerFunctions.java | 80 -- source/mir/util/GeneratorListFunctions.java | 127 -- .../util/GeneratorRegularExpressionFunctions.java | 80 -- source/mir/util/GeneratorStringFunctions.java | 123 -- source/mir/util/HTTPClientHelper.java | 74 ++ source/mir/util/HTTPParsedRequest.java | 63 +- source/mir/util/HTTPRequestParser.java | 5 +- source/mir/util/InternetFunctions.java | 17 +- source/mir/util/ParameterExpander.java | 91 +- source/mir/util/ReflectionRoutines.java | 60 + .../mir/util/ResourceBundleGeneratorFunction.java | 93 -- .../{rss/RSSTest.java => util/StreamCopier.java} | 31 +- source/mir/util/StringParseRoutines.java | 75 +- source/mir/util/StringRoutines.java | 49 +- source/mir/util/StructuredContentParser.java | 11 +- .../BundleGeneratorFunction.java} | 71 +- .../ReflectionGeneratorFunctionAdapter.java | 75 ++ .../ReflectionGeneratorFunctionsAdapter.java | 53 + source/mir/util/xml/XMLParserEngine.java | 28 +- source/mir/util/xml/XMLReaderTool.java | 1 + source/mir/util/xml/XMLSAXParserProvider.java | 5 + source/mir/util/xml/html/HTMLScanner.java | 22 +- .../mir/util/xml/html/HTMLSchemaInformation.java | 3 +- source/mircoders/accesscontrol/AccessControl.java | 11 +- source/mircoders/entity/EntityContent.java | 4 +- source/mircoders/entity/EntityImages.java | 222 +--- source/mircoders/entity/EntityUploadedMedia.java | 21 +- source/mircoders/global/Abuse.java | 26 +- source/mircoders/global/DatabaseEngine.java | 111 ++ source/mircoders/global/MRUCache.java | 7 +- source/mircoders/global/MirGlobal.java | 86 +- source/mircoders/global/MirGlobalExc.java | 38 + source/mircoders/global/MirGlobalFailure.java | 42 + source/mircoders/global/ProducerEngine.java | 97 +- .../localizer/MirAdminInterfaceLocalizer.java | 32 +- .../localizer/MirAntiAbuseFilterType.java | 10 +- .../localizer/MirCachingLocalizerDecorator.java | 12 +- .../mircoders/localizer/MirGeneratorLocalizer.java | 6 +- .../localizer/MirOpenPostingLocalizer.java | 30 +- .../mircoders/localizer/MirProducerLocalizer.java | 9 +- .../basic/MirBasicAdminInterfaceLocalizer.java | 116 +- .../basic/MirBasicAntiAbuseFilterTypes.java | 55 +- .../basic/MirBasicArticlePostingHandler.java | 77 +- .../basic/MirBasicChildArticlePostingHandler.java | 18 +- .../basic/MirBasicCommentPostingHandler.java | 52 +- .../basic/MirBasicDataModelLocalizer.java | 190 ++- .../basic/MirBasicEmailArticleHandler.java | 114 +- .../basic/MirBasicGeneratorLocalizer.java | 19 +- .../basic/MirBasicOpenPostingLocalizer.java | 25 +- .../basic/MirBasicPostingSessionHandler.java | 343 +++++- .../basic/MirBasicProducerAssistantLocalizer.java | 238 +++- .../localizer/basic/MirBasicProducerLocalizer.java | 97 +- .../localizer/basic/MirBasicUtilityFunctions.java | 159 +++ .../basic/actions/ArticleTopicAction.java | 92 ++ .../localizer/basic/filters/ThrottleFilter.java | 237 ++++ source/mircoders/media/AbstractMediaHandler.java | 60 + source/mircoders/media/ImageProcessor.java | 16 +- source/mircoders/media/MediaHandlerAudio.java | 7 +- source/mircoders/media/MediaHandlerGeneric.java | 215 ++-- source/mircoders/media/MediaHandlerImages.java | 63 +- .../mircoders/media/MediaHandlerImagesExtern.java | 24 +- source/mircoders/media/MediaHandlerImagesJpeg.java | 4 +- source/mircoders/media/MediaHandlerMp3.java | 38 +- source/mircoders/media/MediaHandlerOgg.java | 29 - source/mircoders/media/MediaHandlerRealAudio.java | 24 +- source/mircoders/media/MediaHandlerRealVideo.java | 35 +- source/mircoders/media/MediaHandlerVideo.java | 6 +- source/mircoders/media/MediaUploadProcessor.java | 100 +- source/mircoders/media/URLMediaHandler.java | 59 +- .../mircoders/media/UnsupportedMediaTypeExc.java | 45 + source/mircoders/module/ModuleArticleType.java | 10 +- source/mircoders/module/ModuleBreaking.java | 9 +- source/mircoders/module/ModuleComment.java | 11 +- source/mircoders/module/ModuleCommentStatus.java | 9 +- source/mircoders/module/ModuleContent.java | 10 +- source/mircoders/module/ModuleImages.java | 8 +- source/mircoders/module/ModuleLanguage.java | 26 +- source/mircoders/module/ModuleMediaType.java | 45 +- source/mircoders/module/ModuleMediafolder.java | 14 +- source/mircoders/module/ModuleMessage.java | 22 +- source/mircoders/module/ModuleTopics.java | 35 +- source/mircoders/module/ModuleUploadedMedia.java | 2 +- source/mircoders/module/ModuleUsers.java | 18 +- source/mircoders/pdf/PDFGenerator.java | 7 +- .../producer/ContentModifyingProducerNode.java | 5 - .../mircoders/producer/IndexingProducerNode.java | 67 +- .../producer/RadicalendarProducerNode.java | 114 ++ .../mircoders/producer/UnIndexingProducerNode.java | 15 +- .../reader/SupplementalProducerNodeBuilders.java | 142 ++- source/mircoders/search/AudioSearchTerm.java | 19 +- source/mircoders/search/ImagesSearchTerm.java | 26 +- source/mircoders/search/IndexUtil.java | 19 +- source/mircoders/search/VideoSearchTerm.java | 25 +- source/mircoders/servlet/ServletHelper.java | 22 +- source/mircoders/servlet/ServletModuleAbuse.java | 8 +- source/mircoders/servlet/ServletModuleAdmin.java | 51 +- .../servlet/ServletModuleArticleType.java | 5 +- source/mircoders/servlet/ServletModuleAudio.java | 1 - .../mircoders/servlet/ServletModuleBreaking.java | 3 +- source/mircoders/servlet/ServletModuleComment.java | 35 +- .../servlet/ServletModuleCommentStatus.java | 5 +- source/mircoders/servlet/ServletModuleContent.java | 80 +- .../mircoders/servlet/ServletModuleFileEdit.java | 33 +- source/mircoders/servlet/ServletModuleHidden.java | 16 +- source/mircoders/servlet/ServletModuleImages.java | 7 +- .../mircoders/servlet/ServletModuleLanguage.java | 5 +- .../mircoders/servlet/ServletModuleLocalizer.java | 40 +- .../mircoders/servlet/ServletModuleMediaType.java | 4 +- .../servlet/ServletModuleMediafolder.java | 22 +- source/mircoders/servlet/ServletModuleMessage.java | 13 +- .../mircoders/servlet/ServletModuleOpenIndy.java | 95 +- .../mircoders/servlet/ServletModuleOtherMedia.java | 2 - .../mircoders/servlet/ServletModuleProducer.java | 69 +- source/mircoders/servlet/ServletModuleTopics.java | 11 +- .../servlet/ServletModuleUploadedMedia.java | 84 +- source/mircoders/servlet/ServletModuleUsers.java | 28 +- source/mircoders/servlet/ServletModuleVideo.java | 2 - source/mircoders/storage/DatabaseArticleType.java | 3 - source/mircoders/storage/DatabaseComment.java | 7 +- .../mircoders/storage/DatabaseCommentToMedia.java | 18 +- source/mircoders/storage/DatabaseContent.java | 2 +- .../mircoders/storage/DatabaseContentToMedia.java | 18 +- .../mircoders/storage/DatabaseContentToTopics.java | 30 +- templates/admin/FUNCTIONS.template | 64 +- templates/admin/FUNCTIONS_media.template | 13 +- templates/admin/comment.template | 4 +- templates/admin/commentlist.template | 15 +- templates/admin/content.template | 8 +- templates/admin/contentlist.template | 2 +- templates/admin/mediatypelist.template | 2 +- templates/admin/start_admin.template | 1 - templates/admin/superusermenu.template | 1 + web/produced/img/arrow_down.gif | Bin 65 -> 0 bytes web/produced/img/audio_big.gif | Bin 166 -> 0 bytes web/produced/img/audio_small.gif | Bin 66 -> 0 bytes web/produced/img/bashcomp2.gif | Bin 15948 -> 0 bytes web/produced/img/cleft.gif | Bin 1209 -> 0 bytes web/produced/img/dot.gif | Bin 67 -> 0 bytes web/produced/img/extlink.gif | Bin 73 -> 0 bytes web/produced/img/help.gif | Bin 145 -> 0 bytes web/produced/img/intlink.gif | Bin 76 -> 0 bytes web/produced/img/link_small.gif | Bin 71 -> 0 bytes web/produced/img/logo_small.gif | Bin 286 -> 0 bytes web/produced/img/mail_small.gif | Bin 70 -> 0 bytes web/produced/img/maillink.gif | Bin 80 -> 0 bytes web/produced/img/photo_big.gif | Bin 242 -> 0 bytes web/produced/img/photo_small.gif | Bin 860 -> 0 bytes web/produced/img/pointgris.gif | Bin 57 -> 0 bytes web/produced/img/search_icon.gif | Bin 405 -> 0 bytes web/produced/img/sp.gif | Bin 43 -> 0 bytes web/produced/img/text_big.gif | Bin 153 -> 0 bytes web/produced/img/text_small.gif | Bin 76 -> 0 bytes web/produced/img/video_big.gif | Bin 268 -> 0 bytes web/produced/img/video_small.gif | Bin 64 -> 0 bytes web/produced/style/formate.css | 126 -- web/produced/style/mir.css | 5 - 311 files changed, 9026 insertions(+), 8001 deletions(-) create mode 100755 bundles/admin_ro.properties delete mode 100755 doc/CODESTRUCTURE delete mode 100755 doc/CODINGSTYLE delete mode 100755 doc/DC.txt delete mode 100755 doc/INSTALL.mir delete mode 100755 doc/INTERNATIONALIZATION.howto delete mode 100755 doc/KNOWN_BUGS delete mode 100755 doc/LOCALIZER.HOWTO delete mode 100755 doc/LONG.INSTALL.mir delete mode 100755 doc/README delete mode 100755 doc/README.jikes delete mode 100755 doc/TODO.txt delete mode 100755 doc/UPGRADING.mir delete mode 100755 etc/content-types.properties create mode 100755 etc/extralib/README delete mode 100755 etc/open/comment.template delete mode 100755 etc/open/comment_done.template delete mode 100755 etc/open/comment_dupe.template create mode 100755 etc/open/donetranslation.template create mode 100755 etc/open/edittranslation.template delete mode 100755 etc/open/posting.template delete mode 100755 etc/open/posting_done.template delete mode 100755 etc/open/posting_dupe.template rename etc/open/{prepare_mail.template => preparemail.template} (67%) create mode 100755 etc/producer/RSS-full.template create mode 100755 etc/producer/languagebar.template create mode 100755 etc/producer/radicalendar.template create mode 100755 etc/scripts/bundletool.sh create mode 100755 etc/scripts/produce.sh create mode 100755 etc/scripts/reload.sh delete mode 100755 etc/server.xml create mode 100755 lib/commons-dbcp-1.1.jar delete mode 100755 lib/commons-fileupload-1.0-beta-1.jar create mode 100755 lib/commons-fileupload-1.0.jar create mode 100755 lib/commons-httpclient-2.0.jar create mode 100755 lib/commons-pool-1.1.jar delete mode 100755 lib/poolman.jar delete mode 100755 lib/postgresql-72jdbc2.jar create mode 100755 lib/postgresql-74jdbc2.jar delete mode 100755 lib/strutsmesg.jar create mode 100755 lib/xmlrpc-1.2-b1.jar rename {etc => meta}/web.xml (64%) delete mode 100755 scripts/produce.sh delete mode 100755 scripts/search.pl create mode 100755 source/mir/bundle/BasicBundleFactory.java create mode 100755 source/mir/bundle/Bundle.java create mode 100755 source/mir/bundle/BundleFactory.java create mode 100755 source/mir/bundle/BundleLoader.java create mode 100755 source/mir/bundle/CascadingBundleFactory.java create mode 100755 source/mir/bundle/PropertiesBundle.java create mode 100755 source/mir/bundle/PropertiesFileBundleLoader.java create mode 100755 source/mir/generator/tal/SimpleTemplateNodeLibraryRegistry.java rename source/mir/generator/tal/template/{TALBasicTemplateNodeLibrary.java => CoreTemplateNodeLibrary.java} (70%) create mode 100755 source/mir/generator/tal/template/MacroTemplateNodeLibrary.java rename source/mir/generator/tal/template/{TALTemplate.java => Template.java} (75%) create mode 100755 source/mir/generator/tal/template/TemplateLibrary.java rename source/mir/generator/tal/template/{TALTemplateNodeLibrary.java => TemplateNodeLibrary.java} (80%) create mode 100755 source/mir/generator/tal/template/TemplateNodeLibraryRegistry.java rename source/mir/log/{Log.java => LoggerEngine.java} (73%) rename source/mir/log/{TestFramework.java => LoggerExc.java} (80%) create mode 100755 source/mir/log/LoggerFailure.java rename source/mir/producer/{ResourceBundleProducerNode.java => BundleProducerNode.java} (60%) rename source/mir/producer/{ScriptCallingProducerNode.java => ExecuteProgramProducerNode.java} (67%) create mode 100755 source/mir/producer/ExternalDbProducerNode.java delete mode 100755 source/mir/util/GeneratorHTMLFunctions.java delete mode 100755 source/mir/util/GeneratorIntegerFunctions.java delete mode 100755 source/mir/util/GeneratorListFunctions.java delete mode 100755 source/mir/util/GeneratorRegularExpressionFunctions.java delete mode 100755 source/mir/util/GeneratorStringFunctions.java create mode 100755 source/mir/util/HTTPClientHelper.java create mode 100755 source/mir/util/ReflectionRoutines.java delete mode 100755 source/mir/util/ResourceBundleGeneratorFunction.java rename source/mir/{rss/RSSTest.java => util/StreamCopier.java} (76%) rename source/mir/util/{GeneratorExpressionFunctions.java => generator/BundleGeneratorFunction.java} (56%) create mode 100755 source/mir/util/generator/ReflectionGeneratorFunctionAdapter.java create mode 100755 source/mir/util/generator/ReflectionGeneratorFunctionsAdapter.java create mode 100755 source/mircoders/global/DatabaseEngine.java create mode 100755 source/mircoders/global/MirGlobalExc.java create mode 100755 source/mircoders/global/MirGlobalFailure.java create mode 100755 source/mircoders/localizer/basic/MirBasicUtilityFunctions.java create mode 100755 source/mircoders/localizer/basic/actions/ArticleTopicAction.java create mode 100755 source/mircoders/localizer/basic/filters/ThrottleFilter.java create mode 100755 source/mircoders/media/AbstractMediaHandler.java create mode 100755 source/mircoders/media/UnsupportedMediaTypeExc.java create mode 100755 source/mircoders/producer/RadicalendarProducerNode.java delete mode 100755 web/produced/img/arrow_down.gif delete mode 100755 web/produced/img/audio_big.gif delete mode 100755 web/produced/img/audio_small.gif delete mode 100755 web/produced/img/bashcomp2.gif delete mode 100755 web/produced/img/cleft.gif delete mode 100755 web/produced/img/dot.gif delete mode 100755 web/produced/img/extlink.gif delete mode 100755 web/produced/img/help.gif delete mode 100755 web/produced/img/intlink.gif delete mode 100755 web/produced/img/link_small.gif delete mode 100755 web/produced/img/logo_small.gif delete mode 100755 web/produced/img/mail_small.gif delete mode 100755 web/produced/img/maillink.gif delete mode 100755 web/produced/img/photo_big.gif delete mode 100755 web/produced/img/photo_small.gif delete mode 100755 web/produced/img/pointgris.gif delete mode 100755 web/produced/img/search_icon.gif delete mode 100755 web/produced/img/sp.gif delete mode 100755 web/produced/img/text_big.gif delete mode 100755 web/produced/img/text_small.gif delete mode 100755 web/produced/img/video_big.gif delete mode 100755 web/produced/img/video_small.gif delete mode 100755 web/produced/style/formate.css delete mode 100755 web/produced/style/mir.css diff --git a/build.xml b/build.xml index c1309144..d51dd904 100755 --- a/build.xml +++ b/build.xml @@ -1,186 +1,269 @@ - + + + + - + - app.name Base name of this application, used to - construct filenames and directories. + + - deploy.home The name of the directory into which the - deployment hierarchy will be created. - Normally, this will be the name of a - subdirectory under $TOMCAT_HOME/webapps. - deploy.classes The name of the directory that will contain - the class files. - dist.home The name of the base directory in which - distribution files are created. + + + + + - dist.src The name of the distribution JAR file - containing the application source code, - to be stored in the "dist.home" directory. - This filename should end with ".jar". + + - dist.war The name of the Web ARchive (WAR) file - containing our deployable application. - This filename should end with ".war". + - javadoc.home The name of the base directory in which - the JavaDoc documentation for this application - is generated. + - tomcat.home The name of the base directory in which - Tomcat has been installed. This value is - normally set automatically from the value - of the TOMCAT_HOME environment variable. + + - java.home The location of your Java SDK. + + - java.localhome Where your local java classes and jar files - are located. + + + + + + + - tomcat.home The location of the tomcat root directory. + + + ---> + + + - - + + + - - + + + + + + - + - - - - - - - - - - - + + + + + + + + + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - + + + + + + + + - - + + + + + + - - - - - - - - - - - - - - - - - + + + + - + - - - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/admin_en.properties b/bundles/admin_en.properties index a5c7253d..6e7f4faf 100755 --- a/bundles/admin_en.properties +++ b/bundles/admin_en.properties @@ -1,6 +1,6 @@ ########## admin ########## # language: english -# $Id: admin_en.properties,v 1.48.2.22 2004/01/18 17:30:55 zapata Exp $ +# $Id: admin_en.properties,v 1.48.2.23 2004/11/21 22:07:12 zapata Exp $ languagename=English @@ -25,6 +25,7 @@ delete=delete add=add filter=filter attach=attach +deattach=remove list=browse back=back cancel=cancel @@ -147,6 +148,7 @@ commentsearch.field.creator = Author commentsearch.field.main_url = Url commentsearch.field.email = Email commentsearch.field.description = Description +commentsearch.field.comment = Internal comment commentsearch.value = Value commentsearch.publishedstate = Published state @@ -232,6 +234,8 @@ content.operation.hide=hide content.operation.unhide=unhide content.operation.newswire=newswire +content.preview.default = Preview + contentsearch.value = search contentsearch.field = field contentsearch.field.title = Title @@ -239,6 +243,7 @@ contentsearch.field.creator = Author contentsearch.field.contents=Contents contentsearch.field.creator_email = Email contentsearch.field.creator_main_url = Web address +contentsearch.field.comment = Internal comment contentsearch.publishedstate = publication state contentsearch.publishedstate.hidden=hidden @@ -448,12 +453,16 @@ superusermenu.htmltitle = Super-user functions superusermenu.manage = MANAGE superusermenu.topics = topics superusermenu.articletypes = article types -superusermenu.mediatypes = Mediatypes +superusermenu.mediatypes = mediatypes superusermenu.comment_statuses = comment status values superusermenu.users = users superusermenu.languages = languages superusermenu.abuse = apply anti-abuse measures superusermenu.imcs = IMCS (obsolete) +superusermenu.reload= reload bundles, logging and producers + +infomessage.reloadSuccessfull = reload successfull +infomessage.reloadFailed= An error has occurred while reloading:
{0} #abuse @@ -497,6 +506,8 @@ abuse.filter.htmltitle = Edit filter abuse.filtertype.ip = IP Number abuse.filtertype.regexp = Regular expression abuse.filtertype.useragent= User Agent +abuse.filtertype.throttle = Throttle +abuse.filtertype.hostname = Host name abuse.filtererror.title = Error: abuse.filtererror.invalidtype = Invalid filter type diff --git a/bundles/admin_es.properties b/bundles/admin_es.properties index 54b446ed..c6ed7eab 100755 --- a/bundles/admin_es.properties +++ b/bundles/admin_es.properties @@ -1,6 +1,6 @@ ########## admin ########## # language: spanish -# $Id: admin_es.properties,v 1.29.2.3 2004/01/11 20:35:50 zapata Exp $ +# $Id: admin_es.properties,v 1.29.2.4 2004/11/21 22:07:12 zapata Exp $ languagename = Castellano @@ -25,6 +25,8 @@ delete = borrar add = a\u00f1adir filter = filtrar attach = adjuntar +# missing (master value = "remove") +deattach = list = mostrar lista back = atr\u00e1s cancel = cancelar @@ -45,14 +47,11 @@ no_matches_found = \u00a1No se encontraron coincidencias! list.next = siguiente list.previous = anterior -# missing (master value = "Status:") -system.status = -# missing (master value = "Logged in:") -system.loggedin = +system.status = Situaci\u00f3n: +system.loggedin = Identificado: # media - used by image, audio, video and other media -# missing (master value = "Urls") -media.urls = +media.urls = URLs media.created = creado media.changed = \u00faltima modificaci\u00f3n media.published = publicado @@ -73,10 +72,8 @@ media.is_published = Est\u00e1 publicado media.icon = Icono media.nr_of_media = N\u00famero de recursos medi\u00e1ticos (m\u00e1ximo 20) media.nr_of_media.submit = definir n\u00famero -# missing (master value = "Comments ") -media.comments = -# missing (master value = "Articles") -media.articles = +media.comments = Comentarios +media.articles = Art\u00edculos medialist.search_text_in = Buscar texto en @@ -104,8 +101,7 @@ other_medialist.htmltitle = Lista de recursos medi\u00e1ticos # breaking breaking.htmltitle = \u00daltimas noticias breaking.textinfo = (m\u00e1x. 5 l\u00edneas / 250 caracteres) -# missing (master value = "id") -breaking.id = +breaking.id = Id breaking.text = texto breaking.date = fecha @@ -127,12 +123,9 @@ comment.article = Art\u00edculo comment.html = HTML comment.status = Estado comment.language = Idioma -# missing (master value = "All comments") -comment.allcomments = -# missing (master value = "Internal Comment") -comment.comment = -# missing (master value = "(internal)") -comment.comment.info = +comment.allcomments = Todos los comentarios +comment.comment = Comentario Interno +comment.comment.info = (interno) comment.operation.hide = ocultar comment.operation.unhide = desocultar @@ -153,11 +146,11 @@ commentlist.order.articletitle = t\u00edtulo del art\u00edculo commentsearch.field = Buscar commentsearch.field.title = T\u00edtulo commentsearch.field.creator = Autor -# missing (master value = "Url") -commentsearch.field.main_url = -# missing (master value = "Email") -commentsearch.field.email = +commentsearch.field.main_url = URL +commentsearch.field.email = Correo-e commentsearch.field.description = Descripci\u00f3n +# missing (master value = "Internal comment") +commentsearch.field.comment = commentsearch.value = Valor commentsearch.publishedstate = Estado de publicaci\u00f3n @@ -200,16 +193,11 @@ content.content = Contenido content.html = HTML? content.comment = Comentario interno content.internal = (prop\u00f3sito interno) -# missing (master value = "Keywords") -content.keywords = -# missing (master value = "Locked by {0}") -content.lockedby = -# missing (master value = "Lock") -content.lock = -# missing (master value = "Unlock") -content.unlock = -# missing (master value = "Force lock") -content.forcelock = +content.keywords = Palabras clave +content.lockedby = Bloqueado por {0} +content.lock = Bloquear +content.unlock = Desbloquear +content.forcelock = Forzar bloqueo content.attachments = Adjuntos content.images = Im\u00e1genes @@ -253,10 +241,10 @@ contentsearch.field = campo contentsearch.field.title = T\u00edtulo contentsearch.field.creator = Autor contentsearch.field.contents = Contenido -# missing (master value = "Email") -contentsearch.field.creator_email = -# missing (master value = "Web address") -contentsearch.field.creator_main_url = +contentsearch.field.creator_email = Correo-e +contentsearch.field.creator_main_url = Direcci\u00f3n web +# missing (master value = "Internal comment") +contentsearch.field.comment = contentsearch.publishedstate = estado de publicaci\u00f3n contentsearch.publishedstate.hidden = oculto @@ -280,8 +268,7 @@ contentlist.select = Seleccionar # language language.htmltitle = Idioma -# missing (master value = "Id") -language.id = +language.id = Id language.name = Idioma language.code = C\u00f3digo de idioma @@ -299,8 +286,7 @@ login.submit = Aceptar # mediafolder mediafolder.htmltitle = Carpeta de recursos medi\u00e1ticos -# missing (master value = "id") -mediafolder.id = +mediafolder.id = id mediafolder.date = fecha mediafolder.name = nombre mediafolder.location = lugar de origen @@ -312,8 +298,7 @@ mediafolderlist.htmltitle = Lista de carpetas de recursos medi\u00e1ticos # message message.htmltitle = Mensajes -# missing (master value = "id") -message.id = +message.id = id message.date = fecha message.title = t\u00edtulo message.creator = autor @@ -327,10 +312,8 @@ start.htmltitle = Administraci\u00f3n start.content.new = nuevo art\u00edculo start.show = mostrar -# missing (master value = "open comment #") -start.comment.open_by_id = -# missing (master value = "open article #") -start.content.open_by_id = +start.comment.open_by_id = comentario abierto n\u00ba +start.content.open_by_id = art\u00edculo abierto n\u00ba start.content.hidden = art\u00edculos ocultos start.content.not_published = art\u00edculos (aun) sin publicar @@ -341,13 +324,11 @@ start.content.all = Todos los art\u00edculos start.content.search = buscar start.allarticlesoftype = {0} -# missing (master value = "{0}") -start.allcommentswithstatus = +start.allcommentswithstatus = {0} start.producers.title = GENERAR MANUALMENTE start.producers.produceAllNew = generar todos los nuevos -# missing (master value = "generate all new") -start.producers.recipe.allnew = +start.producers.recipe.allnew = generar todos los nuevos start.producers.advanced = p\u00e1gina avanzada (usar con cuidado!) @@ -357,22 +338,20 @@ start.administer.comments = comentarios start.comments.title = COMENTARIOS start.breaking.title = \u00faltimas noticias -# missing (master value = "ARTICLES") -start.articles.title = +start.articles.title = ART\u00cdCULOS start.fileedit.includes.title = editar ficheros start.addandedit.title = A\u00d1ADIR / EDITAR start.extra.title = EXTRA start.search.title = BUSCAR start.other_media.title = otros recursos medi\u00e1ticos start.images.title = im\u00e1genes -# missing (master value = "open image #") -start.images.open_by_id = +start.images.open_by_id = imagen abierta n\u00ba start.video.title = video start.audio.title = audio start.media.title = MEDIA start.mediafolder.title = carpeta de recursos medi\u00e1ticos start.languages.title = IDIOMAS -start.imcs.title = IMCS +start.imcs.title = IMCs start.messageboard.title = TABL\u00d3N DE AVISOS start.messageboard.no_messages = no hay mensajes @@ -383,8 +362,7 @@ start.superusermenu = funciones de super-usuario (usar con cuidado!) topic.htmltitle = tema -# missing (master value = "id") -topic.id = +topic.id = id topic.title = nombre topic.description = descripci\u00f3n topic.filename = nombre del fichero @@ -397,25 +375,17 @@ topiclist.htmltitle = Lista de temas # users user.htmltitle = Usuario user.login = Usuario -# missing (master value = "Your own password") -user.ownpassword = -# missing (master value = "Old password") -user.oldpassword = +user.ownpassword = Tu propia contrase\u00f1a +user.oldpassword = Contrase\u00f1a antigua user.password = Contrase\u00f1a user.password2 = Contrase\u00f1a (confirmaci\u00f3n) user.admin = Administrador -# missing (master value = "Disabled ?") -user.is_disabled = -# missing (master value = "Creation date") -user.creationdate = -# missing (master value = "Last login") -user.lastlogindate = -# missing (master value = "Email address") -user.email = -# missing (master value = "Comment") -user.comment = -# missing (master value = "Profile") -user.profile = +user.is_disabled = Desabilitar? +user.creationdate = Fecha creaci\u00f3n +user.lastlogindate = \u00daltimo login +user.email = Direcci\u00f3n correo-e +user.comment = Comentario +user.profile = Perfil @@ -425,23 +395,23 @@ userlist.htmltitle = Lista de usuarios #articletype articletype.htmltitle = Tipo de art\u00edculo -articletype.id = ID +articletype.id = Id articletype.name = Nombre articletypelist.htmltitle = Lista de tipos de art\u00edculo # mediatypes -mediatypelist.htmltitle = Manage Mediatypes -mediatype.id = id -mediatype.name = Name -mediatype.htmltitle = Mediatype -mediatype.mimetype = MIME-Type -mediatype.classname = Classname -mediatype.tablename = Tabelname +mediatypelist.htmltitle = Gestionar los Tipos de medios +mediatype.id = Id +mediatype.name = Nombre +mediatype.htmltitle = Tipo de medio +mediatype.mimetype = Tipo MIME +mediatype.classname = Nombre de clase +mediatype.tablename = Nombre de tabla #commentstatus commentstatus.htmltitle = Estado de comentario -commentstatus.id = ID +commentstatus.id = Id commentstatus.name = Nombre commentstatuslist.htmltitle = Lista de estados de comentario @@ -468,13 +438,10 @@ producer.job.name = Trabajo producer.job.status = Estado producer.job.date = \u00daltima modificacion producer.job.empty = La cola est\u00e1 vac\u00eda -# missing (master value = "Running time") -producer.job.runningtime = +producer.job.runningtime = Tiempo ejecut\u00e1ndose -# missing (master value = "Cancel selected jobs") -producer.jobqueue.canceljobs = -# missing (master value = "Cancel all pending jobs") -producer.jobqueue.cancelalljobs = +producer.jobqueue.canceljobs = Cancelar trabajos seleccionados +producer.jobqueue.cancelalljobs = Cancelar todos los trabajos pendientes producer.jobqueue.title = Trabajos actuales producer.jobqueue.refresh = refrescar producer.producerlist.title = A\u00f1adir un nuevo trabajo @@ -487,12 +454,19 @@ superusermenu.htmltitle = Funciones de super-usuario superusermenu.manage = GESTIONAR superusermenu.topics = temas superusermenu.articletypes = tipos de art\u00edculo -superusermenu.mediatypes = Mediatypes +superusermenu.mediatypes = Tipos de medios superusermenu.comment_statuses = valores de estados de comentario superusermenu.users = usuarios superusermenu.languages = idiomas superusermenu.abuse = aplicar medidas antiabuso superusermenu.imcs = IMCs (obsoleto) +# missing (master value = "reload bundles, logging and producers") +superusermenu.reload = + +# missing (master value = "reload successfull") +infomessage.reloadSuccessfull = +# missing (master value = "An error has occurred while reloading:
{0}") +infomessage.reloadFailed = #abuse @@ -516,52 +490,44 @@ abuse.log.time = Hora abuse.log.address = N\u00famero de IP abuse.log.object = Objeto abuse.log.browser = Navegador -# missing (master value = "Filter type") -abuse.log.filtertype = -# missing (master value = "Expression") -abuse.log.filterexpression = +abuse.log.filtertype = Tipo de filtro +abuse.log.filterexpression = Expresi\u00f3n abuse.filters = Filtros -# missing (master value = "down") -abuse.filters.movedown = -# missing (master value = "up") -abuse.filters.moveup = +abuse.filters.movedown = abajo +abuse.filters.moveup = arriba +# missing (master value = "bottom") +abuse.filters.movebottom = +# missing (master value = "top") +abuse.filters.movetop = abuse.filter.type = Tipos abuse.filter.expression = Expresi\u00f3n -# missing (master value = "Article ") -abuse.filter.articleaction = -# missing (master value = "Comment ") -abuse.filter.commentaction = -# missing (master value = "Comments (internal usage)") -abuse.filter.comments = -# missing (master value = "Last hit") -abuse.filter.lasthit = -# missing (master value = "Edit filter") -abuse.filter.htmltitle = +abuse.filter.articleaction = Art\u00edculo +abuse.filter.commentaction = Comentario +abuse.filter.comments = Comentarios (uso interno) +abuse.filter.lasthit = \u00daltimo hit +abuse.filter.htmltitle = Editar filtro abuse.filtertype.ip = N\u00famero de IP abuse.filtertype.regexp = Expresi\u00f3n regular -# missing (master value = "User Agent") -abuse.filtertype.useragent = +abuse.filtertype.useragent = Navegador +# missing (master value = "Throttle") +abuse.filtertype.throttle = +# missing (master value = "Host name") +abuse.filtertype.hostname = -# missing (master value = "Error:") -abuse.filtererror.title = -# missing (master value = "Invalid filter type") -abuse.filtererror.invalidtype = -# missing (master value = "Invalid expression for this type") -abuse.filtererror.invalidexpression = +abuse.filtererror.title = Error: +abuse.filtererror.invalidtype = Tipo de filtro inv\u00e1lido +abuse.filtererror.invalidexpression = Expresi\u00f3n inv\u00e1lida para este tipo -# missing (master value = "Anti-abuse filter rules") -abuse.filters.htmltitle = -# missing (master value = "Anti-abuse open posting log") -abuse.log.htmltitle = +abuse.filters.htmltitle = Reglas de filtro antiabuso +abuse.log.htmltitle = Log de env\u00edos abiertos antiabuso # head head.start = inicio head.logout = salir -# missing (master value = "password") -head.changepassword = +head.changepassword = contrase\u00f1a head.help = ayuda head.search = buscar head.logged_in = identificado @@ -603,13 +569,11 @@ media.error.unsupportedformat = El formato del recurso medi\u00e1tico que has su user.error.missingpasswords = La nueva contrase\u00f1a debe ser introducida dos veces user.error.passwordmismatch = Las contrase\u00f1as no son iguales user.error.missingpassword = Es necesario introducir alguna contrase\u00f1a -# missing (master value = "Incorrect password") -user.error.incorrectpassword = +user.error.incorrectpassword = Contrase\u00f1a incorrecta ########## infomessages ########## infomessage.htmltitle = Informaci\u00f3n -# missing (master value = "Your request has been added to the queue.") -infomessage.recipeAddedToQueue = +infomessage.recipeAddedToQueue = Tu petici\u00f3n ha sido a\u00f1adida a la cola. diff --git a/bundles/admin_eu.properties b/bundles/admin_eu.properties index 40a12538..14df8681 100755 --- a/bundles/admin_eu.properties +++ b/bundles/admin_eu.properties @@ -1,717 +1,556 @@ -########## admin ########## -# language: euskera / basque -# $Id: admin_eu.properties,v 1.12.2.3 2004/01/11 20:35:50 zapata Exp $ - -languagename = Euskera - -# general -yes = bai -no = ez -dontcare = ez du axola -all = dena -# missing (master value = "month") -month = -# missing (master value = "year") -year = -# missing (master value = "file") -file = -# missing (master value = "new") -new = -# missing (master value = "by") -by = -# missing (master value = "help") -help = - - -# actions -insert = sartu -save = gorde -edit = aldatu -delete = ezabatu -add = gehitu -filter = iragazi -attach = atxeki -list = zerrenda erakutsi -back = atzera -cancel = utzi -preview = aurrebista -reset = berrasieratu -# missing (master value = "administer") -administer = -# missing (master value = "search") -search = - - -# special -# missing (master value = "fileEdit") -fileedit = - - -# records -records = sarrerak -show_from_to = {0}(e)tik {1}(e)ra bitarteko sarrerak erakusten -no_matches_found = Ez da horrelako sarrerarik aurkitu! -list.next = hurrengoa -list.previous = aurrekoa - -# missing (master value = "Status:") -system.status = -# missing (master value = "Logged in:") -system.loggedin = - -# media - used by image, audio, video and other media -# missing (master value = "Urls") -media.urls = -media.created = sortua -media.changed = aldatua -media.published = argitaratua -media.format = Formatua -media.rights = Egile eskubideak -media.type = Mota -media.mediafolder = Baliabide mediatikoen karpeta -media.title = Izenburua -media.size = Tamaina -media.description = Deskripzioa -media.date = Data -media.location = Jatorrizko lekua -media.creator = Egilea -media.keywords = Hitz gakoak -media.comment = Komentarioa -media.source = Jatorria -media.is_published = Argitaratzeko prest -media.icon = Ikonoa -media.nr_of_media = Baliabide mediatikoen kopurua -media.nr_of_media.submit = Aldatu kopurua -# missing (master value = "Comments ") -media.comments = -# missing (master value = "Articles") -media.articles = - -medialist.search_text_in = Testua non bilatu - - -# image -image.htmltitle = Irudia -imagelist.htmltitle = Irudien zerrenda - - -# audio -audio.htmltitle = Audioa -audiolist.htmltitle = Audio zerrenda - - -# video -video.htmltitle = Bideoa -videolist.htmltitle = Bideo zerrenda - - -# other -other_media.htmltitle = Baliabide mediatikoen zerrenda -# missing (master value = "Other media overview") -other_medialist.htmltitle = - - -# breaking -breaking.htmltitle = Azken albisteak -breaking.textinfo = (gehienez 5 lerrro / 250 letra) -# missing (master value = "id") -breaking.id = -breaking.text = testua -breaking.date = data - -breakinglist.htmltitle = Azken albisteen zerrenda - - -# comment -comment.htmltitle = Komentarioa -comment.date = data -comment.title = izenburua -comment.published = argitaratuta -comment.text = komentarioaren testua -comment.address = helbidea -comment.phone = telefonoa -comment.email = posta elektronikoa -comment.url = URL -comment.creator = egilea -comment.article = Artikuluarena -comment.html = HTML da? -comment.status = Egoera -comment.language = Hizkuntza -# missing (master value = "All comments") -comment.allcomments = -# missing (master value = "Internal Comment") -comment.comment = -# missing (master value = "(internal)") -comment.comment.info = - -# missing (master value = "hide") -comment.operation.hide = -# missing (master value = "unhide") -comment.operation.unhide = - - -#commentlist -commentlist.htmltitle = Komentarioen zerrenda -# missing (master value = "published") -commentlist.published = -commentlist.hidden = izkutua -# missing (master value = "All comments for this article") -commentlist.allcomments = -commentlist.search = bilatu! -# missing (master value = "activate changes") -commentlist.activate = -# missing (master value = "order") -commentlist.order = -# missing (master value = "newest first") -commentlist.order.datedesc = -# missing (master value = "oldest first") -commentlist.order.dateasc = -# missing (master value = "article title") -commentlist.order.articletitle = - -# missing (master value = "Search") -commentsearch.field = -# missing (master value = "Title") -commentsearch.field.title = -# missing (master value = "Author") -commentsearch.field.creator = -# missing (master value = "Url") -commentsearch.field.main_url = -# missing (master value = "Email") -commentsearch.field.email = -# missing (master value = "Description") -commentsearch.field.description = -# missing (master value = "Value") -commentsearch.value = - -# missing (master value = "Published state") -commentsearch.publishedstate = -# missing (master value = "Hidden") -commentsearch.publishedstate.hidden = -# missing (master value = "Published") -commentsearch.publishedstate.published = - -# missing (master value = "Status") -commentsearch.status = - -# missing (master value = "Order") -commentsearch.order = -commentsearch.order.datedesc = data (behera) -commentsearch.order.dateasc = data (gora) -commentsearch.order.articletitle = artikuluaren titulua - -# missing (master value = "Search") -commentsearch.searchbutton = - - -# confirm -confirm.htmltitle = Ezabaketa baieztatu -confirm.really_delete = Sarrera hau ezabatu nahi duzu? -# missing (master value = "This will erase the entry from the database unrecoverably.") -confirm.text = - - -# content -content.htmltitle = Edukia -content.owner = Jabea -# missing (master value = "Language") -content.language = -# missing (master value = "Article type") -content.articletype = -content.topic = Gaia -content.title = Izenburu luzea -content.subtitle = Azpi-izenburua -content.edittitle = Testuinguru izenburua -content.location = Jatorrizko lekua -content.creator = Egilea -content.creator.email = Posta elektronikoa -content.creator.url = Web -content.creator.address = Helbidea -content.creator.telephone = Telefonoa -content.abstract = Deskripzio laburra -content.content = Edukia -content.html = HTML da? -content.comment = Barne komentarioa -content.internal = (barne xederako) -# missing (master value = "Keywords") -content.keywords = -# missing (master value = "Locked by {0}") -content.lockedby = -# missing (master value = "Lock") -content.lock = -# missing (master value = "Unlock") -content.unlock = -# missing (master value = "Force lock") -content.forcelock = - -content.attachments = Atxekiak -content.images = Irudiak -content.audio = Audioa -content.video = Bideoa -content.other = Beste baliabide mediatikoak -content.media = Baliabide mediatikoak -content.addimage = irudia gehitu -# missing (master value = "upload image") -content.uploadimage = -content.addaudio = audio gehitu -# missing (master value = "upload audio") -content.uploadaudio = -content.addvideo = bideoa gehitu -# missing (master value = "upload video") -content.uploadvideo = -content.addother = beste baliabide mediatikoa gehitu -# missing (master value = "upload other media") -content.uploadother = - -content.creationdate = data -content.modificationdate = azken aldaketa -content.status = Egoera -content.type = Artikulu mota -content.import_date = sarreraren data -content.lastchange_date = azken aldaketa -content.create_date = data -content.published = argitaratua -content.comments = Komentarioak - -# missing (master value = "Children & Parents") -content.family = -# missing (master value = "Children") -content.children = -# missing (master value = "view") -content.viewchildren = -# missing (master value = "Parent") -content.parent = -# missing (master value = "view") -content.viewparent = -# missing (master value = "de-select") -content.clearparent = -# missing (master value = "select") -content.selectparent = - -# missing (master value = "hide") -content.operation.hide = -# missing (master value = "unhide") -content.operation.unhide = -# missing (master value = "newswire") -content.operation.newswire = - -# missing (master value = "search") -contentsearch.value = -# missing (master value = "field") -contentsearch.field = -# missing (master value = "Title") -contentsearch.field.title = -# missing (master value = "Author") -contentsearch.field.creator = -# missing (master value = "Contents") -contentsearch.field.contents = -# missing (master value = "Email") -contentsearch.field.creator_email = -# missing (master value = "Web address") -contentsearch.field.creator_main_url = - -# missing (master value = "publication state") -contentsearch.publishedstate = -# missing (master value = "hidden") -contentsearch.publishedstate.hidden = -# missing (master value = "published") -contentsearch.publishedstate.published = - -# missing (master value = "article type") -contentsearch.articletype = - -# missing (master value = "order by") -contentsearch.order = -# missing (master value = "Newest first") -contentsearch.order.datedesc = -# missing (master value = "Oldest first") -contentsearch.order.dateasc = -# missing (master value = "Title") -contentsearch.order.title = -# missing (master value = "Author") -contentsearch.order.creator = -# missing (master value = "Search") -contentsearch.searchbutton = - - -#contentlist -contentlist.htmltitle = Edukien zerrenda -contentlist.comments = komentarioak -# missing (master value = "Select") -contentlist.select = - - -# language -language.htmltitle = Hizkuntza -# missing (master value = "Id") -language.id = -language.name = hizkuntza -language.code = Hizkuntza kodea - -languagelist.htmltitle = Hizkuntzen zerrenda - -# login -login.htmltitle = Sarrera -login.info = Eremu hau baimendutako taldeentzat bakarrik da. Editore lanetan lagundu nahi baduzu, jar zaitez gurekin kontaktuan imceuskalherria-editorial@lists.indymedia.org helbidean mesedez. -login.title = erabiltzailea -login.name = Erabiltzailea -login.password = Pasahitza -login.language = Hizkuntza -login.submit = Ados - - -# mediafolder -mediafolder.htmltitle = Baliabide mediatikoen karpeta -# missing (master value = "id") -mediafolder.id = -mediafolder.date = data -mediafolder.name = izena -mediafolder.location = jatorrizko lekua -mediafolder.keywords = hitz gakoak -mediafolder.comment = komentarioa - -mediafolderlist.htmltitle = Baliabide mediatikoen karpeten zerrenda - - -# message -message.htmltitle = Mezuak -# missing (master value = "id") -message.id = -message.date = data -message.title = izenburua -message.creator = Egilea -message.text = testua -message.textinfo = (gehienez 5 lerrro / 250 letra) - -messagelist.htmltitle = Mezuen zerrenda - -# admin start page -start.htmltitle = Administrazioa - -start.content.new = artikulu berriak -start.show = Erakutsi -# missing (master value = "open comment #") -start.comment.open_by_id = -# missing (master value = "open article #") -start.content.open_by_id = - -start.content.hidden = aritukulu ezkutukoak -start.content.not_published = argitaratzeke dauden artikuluak -start.content.with_media = baliabide mediatikoekin -start.content.last_changes = azken aldaketak -start.content.with_comments = barne xederako komentarioekin -start.content.all = Artikulu guztiak -start.content.search = bilatu - -start.allarticlesoftype = {0} motatako artikulu guztiak -# missing (master value = "{0}") -start.allcommentswithstatus = - -start.producers.title = Euskuz ekoiztu -start.producers.produceAllNew = Dena berria ekoiztu -# missing (master value = "generate all new") -start.producers.recipe.allnew = - -start.producers.advanced = Aukera arreratuak (kontuz honekin!) - -# missing (master value = "ADMINISTER") -start.administer.title = -# missing (master value = "comments") -start.administer.comments = - -start.comments.title = KOMENTARIOAK - -start.breaking.title = AZKEN ALBISTRAK -# missing (master value = "ARTICLES") -start.articles.title = -# missing (master value = "edit include files") -start.fileedit.includes.title = -# missing (master value = "ADD / EDIT") -start.addandedit.title = -# missing (master value = "EXTRA") -start.extra.title = -# missing (master value = "SEARCH") -start.search.title = -start.other_media.title = BESTE MEDIOEN FITXATEGIAK -start.images.title = IRUDIAK -# missing (master value = "open image #") -start.images.open_by_id = -start.video.title = BIDEO FITXATEGIAK -start.audio.title = AUDIO FITXATEGIAK -# missing (master value = "MEDIA") -start.media.title = -start.mediafolder.title = BALIABIDE MEDIATIKOEN ZERRENDA -start.languages.title = IZENBURUA -start.imcs.title = MIGak -start.messageboard.title = Barneko mezuak -start.messageboard.no_messages = ez dago mezurik - -start.superusermenu = Aukera aurreratuak (kontuz honekin!) - - -# topic - -topic.htmltitle = Gaia - -# missing (master value = "id") -topic.id = -topic.title = Izena -topic.description = deskripzioa -topic.filename = Fitxategiaren izena -topic.main_url = Informazio nagusiko orria -topic.archive_url = Fitxategiaren URLa - -topiclist.htmltitle = Gaien zerrenda - - -# users -user.htmltitle = Erabiltzailea -user.login = erabiltzailea -# missing (master value = "Your own password") -user.ownpassword = -# missing (master value = "Old password") -user.oldpassword = -user.password = pasahitza -# missing (master value = "Password (confirmation)") -user.password2 = -user.admin = administratzailea -# missing (master value = "Disabled ?") -user.is_disabled = -# missing (master value = "Creation date") -user.creationdate = -# missing (master value = "Last login") -user.lastlogindate = -# missing (master value = "Email address") -user.email = -# missing (master value = "Comment") -user.comment = -# missing (master value = "Profile") -user.profile = - - - - -userlist.htmltitle = Erabiltzaileen zerrenda - - -#articletype -articletype.htmltitle = Artikuluen motak -articletype.id = ID -articletype.name = Izena - -articletypelist.htmltitle = Artikuluen mota zerrenda - -# mediatypes -mediatypelist.htmltitle = Manage Mediatypes -mediatype.id = id -mediatype.name = Name -mediatype.htmltitle = Mediatype -mediatype.mimetype = MIME-Type -mediatype.classname = Classname -mediatype.tablename = Tabelname - -#commentstatus -commentstatus.htmltitle = Komentarioen egoera -commentstatus.id = ID -commentstatus.name = Izena - -commentstatuslist.htmltitle = Komentarioen egoeraren zerrenda - - - -#file editing -fileedit.htmltitle = Fitxategia aldatu -fileedit.filename = Fitxategiaren izena -# missing (master value = "Subdirectory") -fileedit.subdirectory = - -fileeditlist.htmltitle = Fitxategien aldaketak -fileeditlist.filename = Fitxategiaren izena -# missing (master value = "Subdirectory") -fileeditlist.dirname = - - -#producers -producer.producer = Ekoizlearen izena -producer.verb.name = Lanaren izena -producer.verb.description = Lanaren deskribapena -producer.verb.enqueue = Eskatu - -producer.job.name = Lana -producer.job.status = Egoera -producer.job.date = azken aldaketa -# missing (master value = "Queue is empty") -producer.job.empty = -# missing (master value = "Running time") -producer.job.runningtime = - -# missing (master value = "Cancel selected jobs") -producer.jobqueue.canceljobs = -# missing (master value = "Cancel all pending jobs") -producer.jobqueue.cancelalljobs = -producer.jobqueue.title = Oraingo lanak -producer.jobqueue.refresh = birkargatu -producer.producerlist.title = Lan berri bat gehitu - -producerqueue.htmltitle = Eskuz ekoiztu - - -#superusermenu -superusermenu.htmltitle = Aukera aurreratuak -# missing (master value = "MANAGE") -superusermenu.manage = -superusermenu.topics = Gaien kudeaketa -superusermenu.articletypes = Artiukuluen moten kudeaketa -superusermenu.mediatypes = Mediatypes -superusermenu.comment_statuses = Komentarioen egoeraren kudeaketa -superusermenu.users = Erabiltzailen kudeaketa -superusermenu.languages = Hizkuntzen kudeaketa -# missing (master value = "apply anti-abuse measures") -superusermenu.abuse = -superusermenu.imcs = MIGen zerrendaren kudeaketa (zaharkitua) - - -#abuse -# missing (master value = "anti-abuse measures") -abuse.htmltitle = - -# missing (master value = "Setting") -abuse.setting = -# missing (master value = "Value") -abuse.value = - -# missing (master value = "Turn off open posting") -abuse.disableopenpostings = -# missing (master value = "Require a password for open postings") -abuse.openpostingpassword = -# missing (master value = "Log IPs for open postings") -abuse.logpostings = -# missing (master value = "Logging buffer size") -abuse.logsize = -# missing (master value = "Use cookies for blocked users") -abuse.cookies = -# missing (master value = "Action for blocked article") -abuse.articleaction = -# missing (master value = "Action for blocked comment") -abuse.commentaction = - -# missing (master value = "Show the IP log") -abuse.showlog = -# missing (master value = "Manage filters") -abuse.showfilters = - -# missing (master value = "Time") -abuse.log.time = -# missing (master value = "IP number") -abuse.log.address = -# missing (master value = "Object") -abuse.log.object = -# missing (master value = "Browser") -abuse.log.browser = -# missing (master value = "Filter type") -abuse.log.filtertype = -# missing (master value = "Expression") -abuse.log.filterexpression = - -# missing (master value = "Filters") -abuse.filters = -# missing (master value = "down") -abuse.filters.movedown = -# missing (master value = "up") -abuse.filters.moveup = - -# missing (master value = "Type") -abuse.filter.type = -# missing (master value = "Expression") -abuse.filter.expression = -# missing (master value = "Article ") -abuse.filter.articleaction = -# missing (master value = "Comment ") -abuse.filter.commentaction = -# missing (master value = "Comments (internal usage)") -abuse.filter.comments = -# missing (master value = "Last hit") -abuse.filter.lasthit = -# missing (master value = "Edit filter") -abuse.filter.htmltitle = - -# missing (master value = "IP Number") -abuse.filtertype.ip = -# missing (master value = "Regular expression") -abuse.filtertype.regexp = -# missing (master value = "User Agent") -abuse.filtertype.useragent = - -# missing (master value = "Error:") -abuse.filtererror.title = -# missing (master value = "Invalid filter type") -abuse.filtererror.invalidtype = -# missing (master value = "Invalid expression for this type") -abuse.filtererror.invalidexpression = - -# missing (master value = "Anti-abuse filter rules") -abuse.filters.htmltitle = -# missing (master value = "Anti-abuse open posting log") -abuse.log.htmltitle = - -# head -head.start = hasiera -head.logout = irten -# missing (master value = "password") -head.changepassword = -head.help = laguntza -head.search = bilatu -head.logged_in = erregistraturik zaude - -# foot -foot.top = gora - - -########## dynamic values ########## - -# (users can add new types, how to translate these) -# suggestion if not in bundle use value as Text - - -# Article types -articletypes.openposting = bidalitako mezu ireki bat -articletypes.newswire = newswire -articletypes.feature = azalakoa -articletypes.topicspecial = gaiaz berezia -articletypes.startspecial = berezia - -# Comment status values -# missing (master value = "normal") -commentstatus.normal = - - - -########## error ########## -error.htmltitle = Errakuntza -error.title = Iep! Errakuntza bat gertatu da -error.text = Ondoren datorren mezak agian ez dizu askorik lagunduko, baina seguraski {1}koei bai. -error.text2 = Mesedez, mezu bat bidali {1}ra gorriz agertzen den testuarekin eta egiten ari zinenaren azalpen zehatzarekin. Eskerrik asko! - -usererror.htmltitle = Errakuntza datuetan -usererror.title = Arranopola! Errakuntza bat gertatu da -usererror.text = Sartu dituzun datuek ondoko errakuntza sortarazi dute: -usererror.what_to_do = Mesedez, sakatu atzera botoia eta saiatu berriz - -# missing (master value = "The format of the media you uploaded is not supported") -media.error.unsupportedformat = -# missing (master value = "The new password must be entered twice") -user.error.missingpasswords = -# missing (master value = "The passwords are not equal") -user.error.passwordmismatch = -# missing (master value = "A password must be entered") -user.error.missingpassword = -# missing (master value = "Incorrect password") -user.error.incorrectpassword = - - - - -########## infomessages ########## -infomessage.htmltitle = Oharra -# missing (master value = "Your request has been added to the queue.") -infomessage.recipeAddedToQueue = +########## admin ########## +# language: euskara / basque +# $Id: admin_eu.properties,v 1.12.2.4 2004/11/21 22:07:12 zapata Exp $ + +languagename = Euskara + +# general +yes = bai +no = ez +dontcare = ez du axola +all = dena +month = hilabetea +year = urtea +file = fitxategia +new = berria +by = nork +help = laguntza + + +# actions +insert = sartu +save = gorde +edit = aldatu +delete = ezabatu +add = gehitu +filter = iragazi +attach = atxeki +list = zerrenda erakutsi +back = atzera +cancel = utzi +preview = aurrebista +reset = berrasieratu +administer = administratu +search = bilatu + + +# special +fileedit = fitxategia aldatu + + +# records +records = sarrerak +show_from_to = {0}-(e)tik {1}-(e)ra bitarteko sarrerak erakusten +no_matches_found = Ez da horrelako sarrerarik aurkitu! +list.next = hurrengoa +list.previous = aurrekoa + +system.status = Egoera: +system.loggedin = Identifikatuta: + +# media - used by image, audio, video and other media +media.urls = URLak +media.created = sortua +media.changed = aldatua +media.published = argitaratua +media.format = Formatua +media.rights = Egile eskubideak +media.type = Mota +media.mediafolder = Baliabide mediatikoen karpeta +media.title = Izenburua +media.size = Tamaina +media.description = Deskripzioa +media.date = Data +media.location = Jatorrizko lekua +media.creator = Egilea +media.keywords = Gako-hitzak +media.comment = Komentarioa +media.source = Jatorria +media.is_published = Argitaratzeko prest +media.icon = Ikonoa +media.nr_of_media = Baliabide mediatikoen kopurua +media.nr_of_media.submit = Kopurua aldatu +media.comments = Komentarioak +media.articles = Artikuluak + +medialist.search_text_in = Testua non bilatu + + +# image +image.htmltitle = Irudia +imagelist.htmltitle = Irudien zerrenda + + +# audio +audio.htmltitle = Audioa +audiolist.htmltitle = Audio zerrenda + + +# video +video.htmltitle = Bideoa +videolist.htmltitle = Bideo zerrenda + + +# other +other_media.htmltitle = Beste baliabide mediatikoa +other_medialist.htmltitle = Beste baliabide mediatikoen zerrenda + + +# breaking +breaking.htmltitle = Azken albisteak +breaking.textinfo = (gehienez 5 lerro / 250 letra) +breaking.id = id +breaking.text = testua +breaking.date = data + +breakinglist.htmltitle = Azken albisteen zerrenda + + +# comment +comment.htmltitle = Komentarioa +comment.date = data +comment.title = izenburua +comment.published = argitaratuta +comment.text = komentarioaren testua +comment.address = helbidea +comment.phone = telefonoa +comment.email = posta elektronikoa +comment.url = URL +comment.creator = egilea +comment.article = Artikuluarena +comment.html = HTML da? +comment.status = Egoera +comment.language = Hizkuntza +comment.allcomments = Komentario guztiak +comment.comment = Barne-komentarioa +comment.comment.info = (barne xederako) + +comment.operation.hide = ezkutatu +comment.operation.unhide = agertarazi + + +#commentlist +commentlist.htmltitle = Komentarioen zerrenda +commentlist.published = argitaratuta +commentlist.hidden = ezkutua +commentlist.allcomments = Artikulu honentzako komentario guztiak +commentlist.search = bilatu! +commentlist.activate = aldaketak eragin +commentlist.order = hurrenkera +commentlist.order.datedesc = berriena lehenengo +commentlist.order.dateasc = zaharrena lehenengo +commentlist.order.articletitle = artikuluaren izenburua + +commentsearch.field = Bilatu +commentsearch.field.title = Izenburua +commentsearch.field.creator = Egilea +commentsearch.field.main_url = URL +commentsearch.field.email = E-posta +commentsearch.field.description = Deskripzioa +commentsearch.value = Balorea + +commentsearch.publishedstate = Argitaraketa-egoera +commentsearch.publishedstate.hidden = Ezkutua +commentsearch.publishedstate.published = Argitaratua + +commentsearch.status = Egoera + +commentsearch.order = Hurrenkera +commentsearch.order.datedesc = data (behera) +commentsearch.order.dateasc = data (gora) +commentsearch.order.articletitle = artikuluaren izenburua + +commentsearch.searchbutton = Bilatu + + +# confirm +confirm.htmltitle = Ezabaketa baieztatu +confirm.really_delete = Sarrera hau ezabatu nahi duzu? +confirm.text = Honek behin betiko ezabatuko du sarrera datu-basetik. + + +# content +content.htmltitle = Edukia +content.owner = Jabea +content.language = Hizkuntza +content.articletype = Artikulu-mota +content.topic = Gaia +content.title = Izenburu luzea +content.subtitle = Azpi-izenburua +content.edittitle = Testuinguru izenburua +content.location = Jatorrizko lekua +content.creator = Egilea +content.creator.email = Posta elektronikoa +content.creator.url = Web +content.creator.address = Helbidea +content.creator.telephone = Telefonoa +content.abstract = Deskripzio laburra +content.content = Edukia +content.html = HTML da? +content.comment = Barne komentarioa +content.internal = (barne xederako) +content.keywords = Gako-hitzak +content.lockedby = {0}-(e)k blokeatua +content.lock = Blokeatu +content.unlock = Desblokeatu +content.forcelock = Blokeoa behartu + +content.attachments = Atxekiak +content.images = Irudiak +content.audio = Audioa +content.video = Bideoa +content.other = Beste baliabide mediatikoak +content.media = Baliabide mediatikoak +content.addimage = irudia gehitu +content.uploadimage = irudia igo +content.addaudio = audioa gehitu +content.uploadaudio = audioa igo +content.addvideo = bideoa gehitu +content.uploadvideo = bideoa igo +content.addother = beste baliabide mediatikoa gehitu +content.uploadother = beste baliabide mediatikoa igo + +content.creationdate = data +content.modificationdate = azken aldaketa +content.status = Egoera +content.type = Artikulu-mota +content.import_date = sarreraren data +content.lastchange_date = azken aldaketa +content.create_date = data +content.published = argitaratua +content.comments = Komentarioak + +content.family = Aita eta Semeak +content.children = Semeak +content.viewchildren = ikusi +content.parent = Gurasoa +content.viewparent = ikusi +content.clearparent = aukeraketa kendu +content.selectparent = aukeratu + +content.operation.hide = ezkutatu +content.operation.unhide = agertarazi +content.operation.newswire = newswirea + +contentsearch.value = bilatu +contentsearch.field = eremua +contentsearch.field.title = Izenburua +contentsearch.field.creator = Egilea +contentsearch.field.contents = Edukiak +contentsearch.field.creator_email = E-posta +contentsearch.field.creator_main_url = Web helbidea + +contentsearch.publishedstate = argitaraketa-egoera +contentsearch.publishedstate.hidden = ezkutua +contentsearch.publishedstate.published = argitaratua + +contentsearch.articletype = artikulu-mota + +contentsearch.order = hurrenkera +contentsearch.order.datedesc = Berriena lehenengo +contentsearch.order.dateasc = Zaharrena lehenengo +contentsearch.order.title = Izenburua +contentsearch.order.creator = Egilea +contentsearch.searchbutton = Bilatu + + +#contentlist +contentlist.htmltitle = Edukien zerrenda +contentlist.comments = komentarioak +contentlist.select = Aukeratu + + +# language +language.htmltitle = Hizkuntza +language.id = Id +language.name = hizkuntza +language.code = Hizkuntza-kodea + +languagelist.htmltitle = Hizkuntzen zerrenda + +# login +login.htmltitle = Sarrera +login.info = Eremu hau baimendutako taldeentzat bakarrik da. Editore lanetan lagundu nahi baduzu, jar zaitez gurekin kontaktuan imc-euskalherria-editorial@lists.indymedia.org helbidean mesedez. +login.title = erabiltzailea +login.name = Erabiltzailea +login.password = Pasahitza +login.language = Hizkuntza +login.submit = Ados + + +# mediafolder +mediafolder.htmltitle = Baliabide mediatikoen karpeta +mediafolder.id = id +mediafolder.date = data +mediafolder.name = izena +mediafolder.location = jatorrizko lekua +mediafolder.keywords = gako-hitzak +mediafolder.comment = komentarioa + +mediafolderlist.htmltitle = Baliabide mediatikoen karpeten zerrenda + + +# message +message.htmltitle = Mezuak +message.id = id +message.date = data +message.title = izenburua +message.creator = Egilea +message.text = testua +message.textinfo = (gehienez 5 lerro / 250 letra) + +messagelist.htmltitle = Mezuen zerrenda + +# admin start page +start.htmltitle = Administrazioa + +start.content.new = artikulu berriak +start.show = Erakutsi +start.comment.open_by_id = komentario-ireki zenbakia: +start.content.open_by_id = artikulu-ireki zenbakia: + +start.content.hidden = artikulu ezkutukoak +start.content.not_published = argitaratzeke dauden artikuluak +start.content.with_media = baliabide mediatikoekin +start.content.last_changes = azken aldaketak +start.content.with_comments = barne xederako komentarioekin +start.content.all = Artikulu guztiak +start.content.search = bilatu + +start.allarticlesoftype = {0}-motatako artikulu guztiak +start.allcommentswithstatus = {0} + +start.producers.title = Eskuz ekoiztu +start.producers.produceAllNew = Berri guztia ekoiztu +start.producers.recipe.allnew = Berri guztia ekoiztu + +start.producers.advanced = Aukera arreratuak (kontuz honekin!) + +start.administer.title = ADMINISTRATU +start.administer.comments = komentarioak + +start.comments.title = KOMENTARIOAK + +start.breaking.title = AZKEN ALBISTEAK +start.articles.title = ARTIKULUAK +start.fileedit.includes.title = include fitxategiak aldatu +start.addandedit.title = GEHITU / ALDATU +start.extra.title = EXTRA +start.search.title = BILAKETA +start.other_media.title = BESTE MEDIOEN FITXATEGIAK +start.images.title = IRUDIAK +start.images.open_by_id = irudi-ireki zenbakia: +start.video.title = BIDEO FITXATEGIAK +start.audio.title = AUDIO FITXATEGIAK +start.media.title = MEDIA +start.mediafolder.title = BALIABIDE MEDIATIKOEN ZERRENDA +start.languages.title = IZENBURUA +start.imcs.title = MIGak +start.messageboard.title = Barneko mezuak +start.messageboard.no_messages = ez dago mezurik + +start.superusermenu = Goi-erabiltzaileentzako funtzioak (kontuz honekin!) + + +# topic + +topic.htmltitle = Gaia + +topic.id = id +topic.title = Izena +topic.description = deskripzioa +topic.filename = Fitxategiaren izena +topic.main_url = Informazio nagusiko orria +topic.archive_url = Fitxategiaren URLa + +topiclist.htmltitle = Gaien zerrenda + + +# users +user.htmltitle = Erabiltzailea +user.login = erabiltzailea +user.ownpassword = Zure pasahitza +user.oldpassword = Pasahitz zaharra +user.password = Pasahitza +user.password2 = Pasahitza (berriro) +user.admin = administratzailea +user.is_disabled = Ezgaituta? +user.creationdate = Sorrera-data +user.lastlogindate = Azken sarketa +user.email = Posta elektronikoa +user.comment = Oharra +user.profile = Profila + + + + +userlist.htmltitle = Erabiltzaileen zerrenda + + +#articletype +articletype.htmltitle = Artikulu-motak +articletype.id = Id +articletype.name = Izena + +articletypelist.htmltitle = Artikulu-moten zerrenda + +# mediatypes +mediatypelist.htmltitle = Media-motak kudeatu +mediatype.id = Id +mediatype.name = Izena +mediatype.htmltitle = Media-mota +mediatype.mimetype = MIME-mota +mediatype.classname = Klase izena +mediatype.tablename = Taula izena + +#commentstatus +commentstatus.htmltitle = Komentarioen egoera +commentstatus.id = Id +commentstatus.name = Izena + +commentstatuslist.htmltitle = Komentarioen egoeraren zerrenda + + + +#file editing +fileedit.htmltitle = Fitxategia aldatu +fileedit.filename = Fitxategiaren izena +fileedit.subdirectory = Azpidirektorioa + +fileeditlist.htmltitle = Fitxategien aldaketak +fileeditlist.filename = Fitxategiaren izena +fileeditlist.dirname = Azpidirektorioa + + +#producers +producer.producer = Ekoizlearen izena +producer.verb.name = Lanaren izena +producer.verb.description = Lanaren deskripzioa +producer.verb.enqueue = Eskatu + +producer.job.name = Lana +producer.job.status = Egoera +producer.job.date = azken aldaketa +producer.job.empty = Ilada hutsik dago +producer.job.runningtime = Denbora exekuzioan + +producer.jobqueue.canceljobs = Aukeratutako lanak ezeztatu +producer.jobqueue.cancelalljobs = Egiteke dauden lan guztiak ezeztatu +producer.jobqueue.title = Oraingo lanak +producer.jobqueue.refresh = birkargatu +producer.producerlist.title = Lan berri bat gehitu + +producerqueue.htmltitle = Eskuz ekoiztu + + +#superusermenu +superusermenu.htmltitle = Aukera aurreratuak +superusermenu.manage = KUDEATU +superusermenu.topics = Gaien kudeaketa +superusermenu.articletypes = Artikulu-moten kudeaketa +superusermenu.mediatypes = Media-motak +superusermenu.comment_statuses = Komentarioen egoeraren kudeaketa +superusermenu.users = Erabiltzaileen kudeaketa +superusermenu.languages = Hizkuntzen kudeaketa +superusermenu.abuse = gehiegikerien aurkako neurriak eragin +superusermenu.imcs = MIGen zerrendaren kudeaketa (zaharkitua) + + +#abuse +abuse.htmltitle = gehiegikerien aurkako neurriak + +abuse.setting = Aukera +abuse.value = Balioa + +abuse.disableopenpostings = bidalketa-irekia itxi +abuse.openpostingpassword = bidalketa-irekientzako pasahitza eskatu +abuse.logpostings = bidalketa-irekien IPak gorde +abuse.logsize = Gordetako log-aren tamaina +abuse.cookies = Blokeatutako erabiltzaileekin cookie-ak erabili +abuse.articleaction = Blokeatutako artikuluekin egin beharrekoa +abuse.commentaction = Blokeatutako komentarioekin egin beharrekoa + +abuse.showlog = IPen log-a erakutsi +abuse.showfilters = Iragazkiak kudeatu + +abuse.log.time = Ordua +abuse.log.address = IP zenbakia +abuse.log.object = Objektua +abuse.log.browser = Nabigatzaiela +abuse.log.filtertype = Iragazki-mota +abuse.log.filterexpression = Espresioa + +abuse.filters = Iragazkiak +abuse.filters.movedown = bera +abuse.filters.moveup = gora + +abuse.filter.type = Motak +abuse.filter.expression = Espresioa +abuse.filter.articleaction = Artikulua +abuse.filter.commentaction = Komentarioa +abuse.filter.comments = Komentarioak (barne xederako) +abuse.filter.lasthit = Azken hit-a +abuse.filter.htmltitle = Iragazkia aldatu + +abuse.filtertype.ip = IP Zenbakia +abuse.filtertype.regexp = Espresio erregularra +abuse.filtertype.useragent = Nabigatzailea + +abuse.filtererror.title = Errakuntza: +abuse.filtererror.invalidtype = Iragazki-mota okerra +abuse.filtererror.invalidexpression = Mota honentzako espresio okerra + +abuse.filters.htmltitle = Gehiegikerien aurkako iragazki arauak +abuse.log.htmltitle = Gehiegikerien aurkako bidalketa-irekien log-a + +# head +head.start = hasiera +head.logout = irten +head.changepassword = pasahitza +head.help = laguntza +head.search = bilatu +head.logged_in = erregistraturik zaude + +# foot +foot.top = gora + + +########## dynamic values ########## + +# (users can add new types, how to translate these) +# suggestion if not in bundle use value as Text + + +# Article types +articletypes.openposting = bidalketa-irekia +articletypes.newswire = newswirea +articletypes.feature = azalekoa +articletypes.topicspecial = gaiko berezia +articletypes.startspecial = azaleko berezia + +# Comment status values +commentstatus.normal = normala + + + +########## error ########## +error.htmltitle = Errakuntza +error.title = Iep! Errakuntza bat gertatu da +error.text = Ondoren datorren mezuak agian ez dizu askorik lagunduko, baina seguraski {1}koei bai. +error.text2 = Mesedez, bidali posta elektronikoko mezu bat {1}ra gorriz agertzen den testuarekin eta egiten ari zinenaren azalpenarekin (fitxategia igotzen, artikulua bidaltzen, komentarioa bidaltzen, bilaketa egiten...). Eskerrik asko! + +usererror.htmltitle = Errakuntza datuetan +usererror.title = Arranopola! Errakuntza bat gertatu da +usererror.text = Sartu dituzun datuek ondoko errakuntza sortarazi dute: +usererror.what_to_do = Mesedez, sakatu atzera botoia eta saiatu berriz + +media.error.unsupportedformat = Igo duzun baliabide mediatikoaren formatuarekin ez dugu lan egiten +user.error.missingpasswords = Pasahitz berria birritan sartu beharra dago +user.error.passwordmismatch = Pasahitzak ez dira berdinak +user.error.missingpassword = Pasahitz bat sartu beharra dago +user.error.incorrectpassword = Pasahitza okerra da + + +########## infomessages ########## +infomessage.htmltitle = Oharra +infomessage.recipeAddedToQueue = Zure eskaria ilarara gehitu da diff --git a/bundles/admin_ro.properties b/bundles/admin_ro.properties new file mode 100755 index 00000000..365e75a1 --- /dev/null +++ b/bundles/admin_ro.properties @@ -0,0 +1,530 @@ +########## admin ########## +# language: romanian +# $Id: admin_ro.properties,v 1.2.2.1 2004/11/21 22:07:12 zapata Exp $ + +languagename=Romana + +# general +yes=da +no=nu +dontcare=nuconteaza +all=tot +month=luna +year=an +file=fisier +new=nou +by=de +help=ajutor + + +# actions +insert=insert +save=salveaza +edit=redacteaza +delete=sterge +add=adauga +filter=filtreaza +attach=ataseaza +list=browse +back=inapoi +cancel=canceleaza +preview=preview +reset=reset +administer=administreaza +search=cauta + + +# special +fileedit=redactareFisier + + +# records +records=entries +show_from_to=arata de la {0} la {1} +no_matches_found=No matching entries! +list.next=urmatorul +list.previous=precedentul + + +# media - used by image, audio, video and other media +media.created=creat +media.changed=ultima modificare +media.published=publicat +media.format=format +media.rights=statut copyright +media.type=tip +media.mediafolder=dosar Media +media.title=titlu +media.size=marime +media.description=descriere +media.date=data +media.location=loc +media.creator=autor +media.keywords=keywords +media.comment=remarci (pentru us intern) +media.source=sursa +media.is_published=publicat +media.icon=icon +media.nr_of_media=Number of Media Items (max 20) +media.nr_of_media.submit=define number +media.comments=Comentarii +media.articles=Articole + +medialist.search_text_in=Cauta text in + + +# image +image.htmltitle=Imagine +imagelist.htmltitle=Images overview + + +# audio +audio.htmltitle=Audio +audiolist.htmltitle=Audio overview + + +# video +video.htmltitle=Video +videolist.htmltitle=Video overview + + +# other +other_media.htmltitle=Alta media +other_medialist.htmltitle=Other media overview + + +# breaking +breaking.htmltitle=Ultimile stiri +breaking.textinfo=(max. 5 linii / 250 caractere) +breaking.id = id +breaking.text=text +breaking.date=data + +breakinglist.htmltitle=Breaking news overview + + +# comment +comment.htmltitle=Comment +comment.date=Data +comment.title=Titlu +comment.published=Publicat +comment.text=Comenteaza textul +comment.address=Adresa +comment.phone=Telefon +comment.email=Email +comment.url=Url +comment.creator=Autor +comment.article=Articol +comment.html=HTML +comment.status=Statut +comment.language=Limba +comment.allcomments=Toate comentariile + +comment.operation.hide=ascunde +comment.operation.unhide=neascunde + + +#commentlist +commentlist.htmltitle=comentarii +commentlist.published=publicat +commentlist.hidden=ascuns +commentlist.allcomments=Toate comentariile despre acest articol +commentlist.search=go! +commentlist.activate = activeaza schimbarile +commentlist.order = ordoneaza +commentlist.order.datedesc= data (desc.) +commentlist.order.dateasc= data (asc.) +commentlist.order.articletitle= titlul articolui + +commentsearch.field = Cauta +commentsearch.field.title = Titlu +commentsearch.field.creator = Autor +commentsearch.field.main_url = Url +commentsearch.field.email = Email +commentsearch.field.description = Descriere +commentsearch.value = Value + +commentsearch.publishedstate = Statut publicat +commentsearch.publishedstate.hidden = Ascuns +commentsearch.publishedstate.published = Publicat + +commentsearch.status = Statut + +commentsearch.order = Ordine +commentsearch.order.datedesc= data (desc.) +commentsearch.order.dateasc= data (asc.) +commentsearch.order.articletitle= titlul articolui + +commentsearch.searchbutton = Cauta + + +# confirm +confirm.htmltitle=confirmare de stergere +confirm.really_delete=Esti sigur ca vrei sa stergi acest articol? +confirm.text=Aceasta operatiune este ireversibila. + + +# content +content.htmltitle=Articol +content.owner=Proprietar +content.language=Limba +content.articletype=Tip de articol +content.topic=Subiect +content.title=Titlul Lung +content.subtitle=Titlul scurt +content.edittitle=Titlul de context +content.location=Loc +content.creator=Autor +content.creator.email=E-mail +content.creator.url=Web address +content.creator.address=Adresa +content.creator.telephone=Telefon +content.abstract=Abstract +content.content=Continut +content.html=HTML +content.comment=Comentar intern +content.internal=(intern) + +content.attachments=Atasamente +content.images=Imagini +content.audio=Audio +content.video=Video +content.other=Alta media +content.media=Media +content.addimage=adauga imagine +content.uploadimage=incaraca imagine +content.addaudio=adauga audio +content.uploadaudio=incarca audio +content.addvideo=adauga video +content.uploadvideo=incarca video +content.addother=adauga alta media +content.uploadother=incarca alta media + +content.creationdate=data +content.modificationdate=ultima schimbare +content.status=Statut +content.type=Tip de articol +content.import_date=Data de importare +content.lastchange_date=Ultima modificare +content.create_date=Data +content.published=publicat +content.comments=comentarii + +content.family=Copii si Parinti +content.children=Copii +content.viewchildren=view +content.parent=Parinte +content.viewparent=view +content.clearparent=de-selecteaza +content.selectparent=selecteaza + +content.operation.hide=ascunde +content.operation.unhide=ne-ascunde +content.operation.newswire=newswire + +contentsearch.value = cauta +contentsearch.field = field +contentsearch.field.title = Titlu +contentsearch.field.creator = Autor +contentsearch.field.contents=Continut +contentsearch.field.creator_email = Email +contentsearch.field.creator_main_url = Web address + +contentsearch.publishedstate = statut de publicare +contentsearch.publishedstate.hidden=ascuns +contentsearch.publishedstate.published=publicat + +contentsearch.articletype = tip de articol + +contentsearch.order = in ordine de +contentsearch.order.datedesc=cel mai nou primul +contentsearch.order.dateasc=cel mai vechi primul +contentsearch.order.title=Titlu +contentsearch.order.creator=Aautor +contentsearch.searchbutton=Cauta + + +#contentlist +contentlist.htmltitle=Articole +contentlist.comments=Comentarii +contentlist.select=Selecteaza + + +# language +language.htmltitle=Llimba +language.id=Id +language.name=Limba +language.code=Limbaj cod + +languagelist.htmltitle=Limbi + +# login +login.htmltitle=login +login.info=Aceasta parte este accesibila doar celor care sint autorizati. Daca doresti sa participi in grupul editorial, contacteaza-ne la {0}. +login.title=login +login.name=Login +login.password=Parola +login.language=Limba +login.submit= OK + + +# mediafolder +mediafolder.htmltitle=dosarmedia +mediafolder.id=id +mediafolder.date=data +mediafolder.name=nume +mediafolder.location=loc +mediafolder.keywords=keywords +mediafolder.comment=comentariu + +mediafolderlist.htmltitle=media folder list + + +# message +message.htmltitle=messages +message.id=id +message.date=data +message.title=titlu +message.creator=autor +message.text=text +message.textinfo=(max. 5 linii / 250 caractere) + +messagelist.htmltitle=lista de mesaje + +# admin start page +start.htmltitle=admin + +start.content.new=articol nou +start.show=arata +start.comment.open_by_id=open comment # +start.content.open_by_id=open article # + +start.content.hidden=arata toate articolele ascunse +start.content.not_published=articole inca nepublicate +start.content.with_media=cu media +start.content.last_changes=ultimele schimbari +start.content.with_comments=cu comentarii interne +start.content.all=toate articolele +start.content.search=cauta + +start.allarticlesoftype={0} +start.allcommentswithstatus={0} + +start.producers.title=GENEREAZA MANUAL +start.producers.produceAllNew=genereaza totul nou +start.producers.recipe.allnew=genereaza totul nou + +start.producers.advanced=pagina avansata (utilizati cu grija!) + +start.administer.title=ADMINISTREAZA +start.administer.comments=comentarii + +start.comments.title=COMENTARII + +start.breaking.title=ultimele stiri +start.articles.title=ARTICOLE +start.fileedit.includes.title=edit include files +start.addandedit.title=ADD / EDIT +start.extra.title=EXTRA +start.search.title=SEARCH +start.other_media.title=alta media +start.images.title=poze +start.video.title=video +start.audio.title=audio +start.media.title=MEDIA +start.mediafolder.title=dosarmedia +start.languages.title=LIMBI +start.imcs.title=IMCS +start.messageboard.title=MESSAGEBOARD +start.messageboard.no_messages=no messages + +start.superusermenu=super-user functions (use with care!) + + +# topic + +topic.htmltitle=topic + +topic.id=id +topic.title=nume +topic.description=descriere +topic.filename=numefisier +topic.main_url=main infopage +topic.archive_url=url arhiva + +topiclist.htmltitle=topiclist + + +# users +user.htmltitle=User +user.login=Login +user.ownpassword=Your own password +user.oldpassword=Old password +user.password=Password +user.password2=Password (confirmation) +user.admin=Admin + +userlist.htmltitle=Users + + +#articletype +articletype.htmltitle=Tip de articol +articletype.id=id +articletype.name=Name + +articletypelist.htmltitle=Tipuri de articole + + + +#commentstatus +commentstatus.htmltitle=Statut comentar +commentstatus.id=id +commentstatus.name=Nume + +commentstatuslist.htmltitle=Comment status values + + + +#file editing +fileedit.htmltitle = Editeza fisier +fileedit.filename = Numefisier +fileedit.subdirectory = Subdirectory + +fileeditlist.htmltitle = Fisier cu posibilitate de editare +fileeditlist.filename = Filename +fileeditlist.dirname = Subdirectory + + +#producers +producer.producer = Producer name +producer.verb.name = Task name +producer.verb.description = Task description +producer.verb.enqueue = enqueue + +producer.job.name = Job +producer.job.status = Statut +producer.job.date = Ultima schimbare +producer.job.empty = Queue is empty +producer.job.runningtime = Running time + +producer.jobqueue.canceljobs = Cancel selected jobs +producer.jobqueue.cancelalljobs = Cancel all pending jobs +producer.jobqueue.title = Current jobs +producer.jobqueue.refresh = refresh +producer.producerlist.title = Add a new job + +producerqueue.htmltitle = Genereaza manual + + +#superusermenu +superusermenu.htmltitle = Super-user functions +superusermenu.manage = MANAGE +superusermenu.topics = subiecte +superusermenu.articletypes = tipuri de articole +superusermenu.comment_statuses = comment status values +superusermenu.users = users +superusermenu.languages = +superusermenu.abuse = apply anti-abuse measures +superusermenu.imcs = IMCS (obsolete) + + +#abuse +abuse.htmltitle = anti-abuse measures + +abuse.setting = Setting +abuse.value = Value + +abuse.disableopenpostings=Turn off open posting +abuse.openpostingpassword=Require a password for open postings +abuse.logpostings=Log IPs for open postings +abuse.logsize=Logging buffer size +abuse.cookies=Use cookies for blocked users +abuse.articleaction=Action for blocked article +abuse.commentaction=Action for blocked comment + +abuse.showlog=Show the IP log +abuse.showfilters=Manage filters + +abuse.log.time=Time +abuse.log.address=IP number +abuse.log.object=Object +abuse.log.browser=Browser +abuse.log.filtertype=Filter type +abuse.log.filterexpression=Expression + +abuse.filters = Filters +abuse.filters.movedown = move down +abuse.filters.moveup = move up + +abuse.filter.type = Type +abuse.filter.expression = Expression +abuse.filter.articleaction = Article +abuse.filter.commentaction = Comment +abuse.filter.comments = Comments (internal usage) +abuse.filter.lasthit = Last hit +abuse.filter.htmltitle = Edit filter + +abuse.filtertype.ip = IP Number +abuse.filtertype.regexp = Regular expression + +abuse.filtererror.title = Error: +abuse.filtererror.invalidtype = Invalid filter type +abuse.filtererror.invalidexpression = Invalid expression for this type + +abuse.filters.htmltitle = Anti-abuse filter rules +abuse.log.htmltitle = Anti-abuse open posting log + +# head +head.start=start +head.logout=logout +head.changepassword=password +head.help=help +head.search=search +head.logged_in=logged in + +# foot +foot.top=top + + +########## dynamic values ########## + +# (users can add new types, how to translate these) +# suggestion if not in bundle use value as Text + + +# Article types +articletypes.openposting=Open posting +articletypes.newswire=Newswire +articletypes.feature=Feature +articletypes.topicspecial=Topic-special +articletypes.startspecial=Startpage-special + +# Comment status values +commentstatus.normal=normal + + + +########## error ########## +error.htmltitle=the system caused an error +error.title=The system caused an error +error.text=This can happen. Even if the following error message is not be comprehensible for you,
it might be helpful to {1}: +error.text2=So please send an e-mail with the red text and detailed information regarding the events that led to this error to {1}. Thanks! + +usererror.htmltitle=Input error +usererror.title=Input error +usererror.text=Your input caused the following error: +usererror.what_to_do=Please press the back button and try it again + +media.error.unsupportedformat=The format of the media you uploaded is not supported +user.error.missingpasswords=The new password must be entered twice +user.error.passwordmismatch=The passwords are not equal +user.error.missingpassword=A password must be entered +user.error.incorrectpassword= Incorrect password + + + + +########## infomessages ########## +infomessage.htmltitle = Information +infomessage.recipeAddedToQueue = Your request has been added to the queue. + diff --git a/dbscripts/help_arttype.sql b/dbscripts/help_arttype.sql index f4e3d869..0bdad5e7 100755 --- a/dbscripts/help_arttype.sql +++ b/dbscripts/help_arttype.sql @@ -4,3 +4,4 @@ INSERT INTO "article_type" VALUES (1,'newswire'); INSERT INTO "article_type" VALUES (2,'feature'); INSERT INTO "article_type" VALUES (3,'topicspecial'); INSERT INTO "article_type" VALUES (4,'startspecial'); +INSERT INTO "article_type" VALUES (5,'translation'); diff --git a/dbscripts/help_lang.sql b/dbscripts/help_lang.sql index 6cf6a0b2..9af2e5ac 100755 --- a/dbscripts/help_lang.sql +++ b/dbscripts/help_lang.sql @@ -2,3 +2,4 @@ -- \connect - postgres INSERT INTO "language" VALUES (0,'deutsch','de'); INSERT INTO "language" VALUES (1,'english','en'); +INSERT INTO "language" VALUES (2,'other','ot'); diff --git a/doc/CODESTRUCTURE b/doc/CODESTRUCTURE deleted file mode 100755 index d89260e7..00000000 --- a/doc/CODESTRUCTURE +++ /dev/null @@ -1,153 +0,0 @@ -------------------------------------------------------------------------------- - -A short intro to the code-structure of Mir - -------------------------------------------------------------------------------- - -In the java-source tree you will find the following: - - - two classes (OpenMir and Mir) - - two packages (mir and mircoders) - - -Servlets: -------------------------------------------------------------------------------- - -Looking from the request of a client browser onto MIR, the http-request is -passed via Apache/Tomcat to either Mir.class or OpenMir.class. Mir.class -handles all request that deal with internal administration tasks of MIR. -OpenMir is the Servlet that deals with all open tasks: adding comments or -articles/media to the system. - -These servlets don't do much but dispatching the tasks to an underlying -code level, called ServletModules. OpenMir.class is basically a special -case of Mir.class, no authentication is needed, and only two underlying -ServletModule are used. - -The following explanation is about how requests are passed through, and -responses to the client-browser are generated. The request has to pass -through up to four levels of code (and from there asking the database), -until it collected all the necessary data or performed all necessary -tasks, to be able to respond. - - -ServletModules: -------------------------------------------------------------------------------- - -The ServletModules are called via reflection java-api. The http-request -parameter "module=XXX" and "do=YYY" are evaluated. A method -YYY(HttpRequest,HttpResponse) is called in ServletModuleXXX. - -A common mistake for those new to Java is to look for usage of a class in -the code by doing a "grep -r ClassName" or something like that. In this -case, grep -r ServletModuleImages for example will turn up nothing except -for ServletModuleImages itself.. that is because of reflection as -explained above. - -The media handlers in mir.media.* work the same way as well. - - Database/Entity: -------------------------------------------------------------------------------- -- db: singeltons, object-representation of db-table, *low-level* access, -generating entities, does all the dirty JDBC work. There is a Database -Class for every table in the DB. - -If an Entity wants to store itself in the media table, it has to have a -storage object of type DatabaseMedia.... - -When you ask a storage object to get something, it hands back an Entity. -[through Database*.selectByWhereClause(), selectById().] - -- entity: representation of row. Contains the contents of "select * from -dbname where id=rowid" in a HashMap. accessible via -Entity.getValue("keyname"). One can do Entity.setValue(..., -Entity.update() which syncs the Hash with the DB row and Entity.insert() -to insert the HashMap as a new row, etc... basically high level DB access. -The text component of an article is an entity (EntityContent, a row from -the content table.) In short this is how we fetch content (whatever that -may be: actual data, media meta-data, media_types, etc..) from the DB and -write to the DB. Everything has to be reprented as an Entity. - -All Entities must have a StorageObject (theStorage) which is a Database -object of the appropriate type. it is the connection between the entity -data and the DB table itself. The only way to get an Entity other than -asking a storage object to fetch one is to construct one by passing the -storage object to the Entity Konstruktor. - -There is also EntityList, a list of entities.. - -Modules: -------------------------------------------------------------------------------- - -- This one is a little grey... It's pretty much a wrapper around Database -and Entity combined, so it's a half level higher up or so. It's not always -necessary to use/have a Module either.. A usage example: you can do -ModuleName.getByWhereClause() and it returns a list of Entities that match -the query. Like entities you must have a StorageObject to access the DB. -but unlike Entity, you can start out without one. Modules use Entity and -Database objects internally. [Actually it uses Database object internally -and returns Entitys...] - -Also I believe the intention was/is that it should be used in place of -Entity for any *logic* that would normally have to into an Entity as -Entity should be free of a case specific logic in theory. But that's not -always true if you use EntityImages as an example, but that seems to be -because EntityImages needs low-level DB connections. - -Producer -------------------------------------------------------------------------------- - -Well, what makes Mir different than other Content Management Systems is -that it does not generate the content pages dynamically or use simple -caching methods. Rather it generates static .[s]html files exclusively. -This makes mir very fast under high viewing loads as it does not use -servlets for this at all. It also makes it very easy to mirror as the -mirrors do not have to run any Mir code, they only have to have a static -webserver. In fact the first site to use Mir, germany.indymedia.org is on -a whole other machine on another continent than the machine that -*produces* the static files. Germany.indymedia.org already has 3 mirrors. - -The mircoders.producer.* classes are responsible for creating these static -.html files and the filesystem structure that they reside in. This -includes files that are article summaries and files that are the whole -article themselves. Some media types also require Producers. - -If the main content *viewing* server is on another host, the FS tree is -then rsync'ed to the viewing host. - -The Producers are called exclusively from the ServletModules in -mircoders.servlet.*. They are called when a new article/comment is added, -or when an administrator/moderator makes modifications to the site or when -a manual update is desired. The method "handle()" is the one that does all -work it takes parameters that tell it to force update all files even if -their contents is unchanged, etc.. some Producers take an article ID as an -argument telling them to create the html page representing the article and -any summary pages that might be changed due to the addition of the -article. - -Producers of course use Entities, Database, MediaHandler and Module -objects internally. - -A dB field called is_produced is used to determine wether or not an Object -needs to be produced. - -Oh and before I forget, it generates the pages based on a template. It -uses the Freemarker templating system. Doc on freemarker is available at -freemarker.sourceforge.net I believe. - -TODO: In theory it would be cool if we could abstract the output mechanism -further to use other types of templates and to generate content other than -HTML (like WAP for example). - -Media Handlers -------------------------------------------------------------------------------- -They are kind of helper classes to deal with different representations of -media types. They are called via the java reflection API. The class names -are resolved through the media_type table. See -source/mir/media/MirMedia.java for documentation. - -Helper classes -------------------------------------------------------------------------------- -mir.misc.* (source/mir/misc/*) contains a bunch of classes that do Regexp, -file handling and those sorts of things. Always look here first before -writing such a thing. diff --git a/doc/CODINGSTYLE b/doc/CODINGSTYLE deleted file mode 100755 index 654af7ac..00000000 --- a/doc/CODINGSTYLE +++ /dev/null @@ -1,36 +0,0 @@ -last changed: $Date: 2002/12/08 07:05:56 $ ------------------------- - -please us spaces not tabs for indents. all indents should be 2 spaces wide. - -If you use the vim editor, below is a good .vimrc entry for java files that -makes all tabs appear 2 chars. wide and makes indenting using the TAB key create -2 real spaces. It also sets the shiftwidth to 2 spaces. - -in your .vimrc add the following: - -autocmd FileType java source /path/to/file/.vimrc.java - -create .vimrc.java and add the following: - -set tabstop=2 -set shiftwidth=2 -set expandtab - -if you can, please try to make your code terminal friendly so a line should -not be more than 80 characters wide pls. Not all mir code is like this and it -is not required (well what really is required?) - -For java code, class names usually begin with a capital letter. e.g -StringUtils.java. Names for variables and methods should begin with a lower case -letter. However, if a variable or method is composed of more than one word -(glued together of course) the second and following word(s) should begin with -a capitalized letter. for example in the following code snippet: - -String name = "titi"; -Entity contentEntity = getContent(); -contentEntity.setPropertyForValue("name", name); - -some java code convention docs: - -http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html diff --git a/doc/DC.txt b/doc/DC.txt deleted file mode 100755 index d2511780..00000000 --- a/doc/DC.txt +++ /dev/null @@ -1,128 +0,0 @@ -Dublin Core (http://purl.org/DC) ----------------------------------------------------------------- - -Bei der Dublin Core Metadata Initiative handelt es sich um ein -Projekt, dass einen "common core of semantics for resource -description" schafft. Selbstdarstellung unter - - http://purl.org/DC/about/index.htm - - -Die Datenbankstruktur von Webdb/NA von der Bennenung soweit moeglich -an das - - "Dublin Core Metadata Element Set, Version 1.1: Reference Description - Beschreibung unter http://purl.org/DC/documents/rec-dces-19990702.htm" - -angelehnt. Dublin Core Metadaten werden entsprechend untenstehendem Matching -in die Header der produzierten Seiten geschrieben... - - -Matching: - -Dublin Core umfasst 15 Attribute. Beschreibung der Attribute siehe oben. -Angaben in eckigen Klammern beziehen sich auf Funktionalitaeten, die z.Z. -noch nicht implementiert sind. - -Im folgenden, wie die DC-Attribute in den Tabellen repraesentiert sind: - -MEDIA/IMAGE Tabelle: - -1. DC Element: Title - MEDIA Element: title - -2. DC Element: Creator - MEDIA Element: creator / to_creator - -3. DC Element: Subject - MEDIA Element: keywords [/ keywords n:m] - -4. DC Element: Description - MEDIA Element: desciption - -5. DC Element: Publisher - MEDIA Element: to_publisher - -6. DC Element: Contributor - MEDIA Element: to_publisher - -7. DC Element: Date - MEDIA Element: publish_date - -8. DC Element: Type - MEDIA Element: to_media_type.dcname - -9. DC Element: Format - MEDIA Element: to_img_format.mimetype - [fuer video/audio dann analog] - -10. Element: Identifier - MEDIA Element: publish_server + publish_path - -11. DC Element: Source - MEDIA Element: source - -12. DC Element: Language - MEDIA Element to_lang - -13. DC Element: Relation - MEDIA Element: to_media_folder - -14. DC Element: Coverage - MEDIA Element: place [ / to_place] - -15. DC Element: Rights - MEDIA Element: to_rights - -------------------------------------------------------------------------- - - -CONTENT Tabelle: -MEDIA/IMAGE Tabelle: - -1. DC Element: Title - MEDIA Element: title - -2. DC Element: Creator - MEDIA Element: creator / to_creator - -3. DC Element: Subject - MEDIA Element: keywords [/ keywords n:m] - -4. DC Element: Description - MEDIA Element: desciption - -5. DC Element: Publisher - MEDIA Element: to_publisher - -6. DC Element: Contributor - MEDIA Element: to_publisher - -7. DC Element: Date - MEDIA Element: publish_date - -8. DC Element: Type - MEDIA Element: to_media_type.dcname - -9. DC Element: Format - MEDIA Element: to_img_format.mimetype - [fuer video/audio dann analog] - -10. Element: Identifier - MEDIA Element: publish_server + publish_path - -11. DC Element: Source - MEDIA Element: source - -12. DC Element: Language - MEDIA Element to_lang - -13. DC Element: Relation - MEDIA Element: to_media_folder - -14. DC Element: Coverage - MEDIA Element: place [ / to_place] - -15. DC Element: Rights - MEDIA Element: to_rights - diff --git a/doc/INSTALL.mir b/doc/INSTALL.mir deleted file mode 100755 index a4411bb5..00000000 --- a/doc/INSTALL.mir +++ /dev/null @@ -1,259 +0,0 @@ -MIR INSTALLATION HOWTO - -Last updated: $Date: 2003/12/03 18:10:45 $ ----------------------------------------------------------------- - -Here is a short installation-howto of Mir. - - -prerequisites: - -- tomcat 4.0.4+ or 3.3 (4.0.3 and below have some bad bugs) - tomcat is available from http://jakarta.apache.org/tomcat/ -- apache 1.3.x. with mod_jk.so. As far as I can tell the connector for 2.x is - still rather undocumented. http://httpd.apache.org -- postgres 7.1+ -- ant (a java-based make) -- jaxp-1.1 (a SAX 2.0 compliant XML parser, comes with ant >= 1.4) -- the JAI image framework (Java Advanced Imaging) version 1.1.2 . Get it from - java.sun.com. You need both: JAI and JAI Image I/O. Install those two in - the JRE running tomcat. - -- A good reading of Tomcat, Apache and Postgresql documentation if you are not - familiar with any of them. The documentation is available at: - http://jakarta.apache.org/tomcat/tomcat-4.0-doc/index.html, - http://httpd.apache.org/docs/ and http://www.postgresql.org respectively. - -1. checkout the cvs - -CVS LOGIN: - - cvs -d :pserver:anonymous@mir.indymedia.org:/var/lib/cvs login - password: anonymous - -CVS CHECKOUT: - - cvs -d :pserver:anonymous@mir.indymedia.org:/var/lib/cvs co -r MIR_1_1 mir - - -2. customize the config: - - cd mir/etc - cp config.properties-dist config.properties - -now customize config.properties for your needs. - - -3. configure the perms.sh file if neccessary -- IMPORTANT! READ THIS! -We provide a script that sets all files' and direcories' permissions to -a quite reasonable state. This script gets automagically called by -ant after compilationl. The most important thing you have to do after -compiling Mir is to ensure that the log files -- especially -dbentity.log -- are not readable by users that could compromise -system security, because all passwords and the like will be logged here. - - cp perms.sh-dist perms.sh - -Now, change the install directory and group in perms.sh - - edit perms.sh - -4. There is NO step 4!! - -5. compile. For this step, you have to make sure that the TOMCAT_HOME -environment variable is set to the root of your tomcat installation. -The build.xml compile target will give up if this is not set. - -Do this as root so the permissions script is able to set -the permissions and owners correctly. - - ant - - -6. Link in the webapps directory of tomcat to the install directory (the -directory is in mir/bin/mir (Here and in the rest of this document, -we assume you called the link "Mir", but this could be named anything.) - cd ${TOMCAT_HOME}/webapps - ln -s /path/to/mir/bin/mir Mir - -with tomcat 4.0.x, you could dynamically reload and stop the Mir webapp without -restarting tomcat by using the "Manager App" with the following url: - -http://localhost:8080/manager/stop?path=/Mir - -This is practical if you are running several installations of mir on one -tomcat or other webapps and can't afford to shutdown all of them. -See the tomcat documentation to learn how to enable and use the manager app. - -7. Follow the installation instructions of JAI / JAI Image I/O. - -8a. create a new database -The database name should be the same as in config.properties. Please look at -the section "Database.*" to look up the names or change them to your needs. - -It is wise in terms of system security to use an unprivileged user for this -task instead of the superuser. This is because if Mir uses the superuser to -connect to the database and anybody manages to find out the password Mir -uses to connect, the attacker can take over the complete database. So, in -the following examples, we assume that the database name is "Mir", the -database user will be "joe" and the password is "joshua". Please note that -this particular password is far from being a good one. Watch "Wargames" for -details. =B) - - -To access the database as the database superuser, you either have to log in -as postgres on Unix level (which we don't recommend because you will need -another user to have a login shell and a password which makes system -penetration more likely) or you have to tell PostgreSQL with each -application call that you want to connect as a specific user. In the -following example we'll create the mir database as postgreSQL user -"pete". - - cd mir/dbscripts - su postgres - ./createmirdb.sh mir pete joe joshua - -8b. Apply neccessary changes to config.properties - -Please open config.properties and look for the lines that begin with -"Database.". The interesting properties are "Username", "Password", "Host" -and "Name". Change these properties so that they reflect the settings you -used to create the database and the user. - -You should make sure that no copy of config.properties (neither in mir nor -in Mir/src nor in Mir/WEB-INF/classes nor in the directory tree you compiled -Mir from) is world-readable. Else you wouldn't have to install a password, -anyway. - -8c. Setup PostgreSQL so that all localhost connections have to pass a -password - -In /etc/postgresql/pg_hba.conf, change the line with 127.0.0.1 as follows: - -host all 127.0.0.1 255.0.0.0 password - -This means: All connections from 127.0.0.1 to any database will have to -authenticate themselves with a password. Please refer to the PostgreSQL -documentation if you want a different authentication setup. Make sure -however that mir can connect to it's database using password authentication. - -9. For now, there's no step 9 either. - -10. Tweak mime-type extensions mappings in etc/web.xml file. - -*** Note the defaults should be o.k for most installations *** - -Add or remove any mime types you wish to support. This is used to figure -out the mime-type when (broken browsers?) browsers don't send the mime-type -in the content-type header field when uploading a media file. Note add the -moment you still have to add these to the media_type SQL table as well which -maps the mime-types to the correct mediaHandler class. See the comments in -the MirMedia class in javadoc for more details. - -11. restart tomcat - -12. configure mod_jk - -There are 2 ways to do this. auto-generation of mod_jk.conf or manula JKMount -lines. (rumour has it that Tomcat 4.0.x doesn't support auto-generation, but -this is unconfirmed). - -In both examples please note that the JkWorkersFile line only needs to appear -once per Apache config. - -Also this assumes that your tomcat installation has it's ajp13 conenctor -turned on. See tomcat's server.xml file and documentation for this. Chances -are that it is turned on. - -Method a). The automatic mod_jk.conf method: - -insert the following patch into /etc/apache/httpd.conf. Edit the directories -to suit your needs. - - -JkWorkersFile /path/to/tomcat/conf/workers.properties -Include /path/to/tomcat/conf/mod_jk.conf-auto - - -Do not put any JkMount lines into your httpd.conf! - -If mod_jk.conf-auto doesn't get written or is 0 bytes in size, check your -system for file ownership/permissions problems. - -Method b). Manual JKMount lines - -insert the following patch into /etc/apache/httpd.conf. Edit the directories -to suit your needs. - - -JkWorkersFile /path/to/tomcat/conf/workers.properties -JkMount /Mir ajp13 -JkMount /Mir/* ajp13 - - - -13. configure apache for the static site - -* Make sure that if you are using a non standard character set enconding that - Apache doesn't accidentally send the wrong encoding in the HTTP headers. -edit http.conf: -* set the document root to the same directory as in the mir config file -* enable shtml includes: - - add LoadModule includes_module /usr/lib/apache/1.3/mod_include.so - - make sure your directory contains "Options Includes" -* Determine if you need to modify any apache mime-mappings - - The web-server host must recognize the .m3u, .pls and other file extensions - and send the proper "audio/x-mpegurl" and "audio/x-scpls" mime-types - respectively. If the web server is apache, it's easy, just - add: - - audio/x-mpegurl m3u - audio/x-scpl pls - - to the file pointed to by the "TypesConfig" command in your apache config - file. Or add and equivalent AddType command to your httpd.conf. Of course - this assumes that the mod_mime is loaded. - -that's it :) - -now the admin-application is accesable via: - - http://host/Mir/servlet/Mir - -and the openposting-servlet via - - http://host/Mir/servlet/OpenMir - -standard login is admin/indymedia. See the webdb_users SQL table to change/add -users or passwords. - - -SEARCHING - -The Mir code offers no internal search facilities, rather, the design -expects the use of an external program to crawl and index the static -site. One (recommended) tool for doing this is htdig -(http://htdig.org), which generates static databases of the site -content and then accesses those databases through a very fast CGI -program written in C. In the scripts directory, a perl CGI script -which wraps calls to htsearch is provided (scripts/search.pl) which -will allow searching based off of media type. (This is possible -because the standard templates will include META keywords like -hasAudio, hasVideo, etc.) - -UPGRADING - -see the UPGRADING.mir file. - -TROUBLESHOOTING - -You can give these a try if anything goes wrong: - -+ Restart Tomcat. Especially after compiling the sources Tomcat has to be - restarted. - -+ Check file permissions and ownership. Try and run perms.sh. - ----------------------------------------------------------------- - -$Date: 2003/12/03 18:10:45 $ - the Mir coders diff --git a/doc/INTERNATIONALIZATION.howto b/doc/INTERNATIONALIZATION.howto deleted file mode 100755 index b6b2e47a..00000000 --- a/doc/INTERNATIONALIZATION.howto +++ /dev/null @@ -1,53 +0,0 @@ -MIR INTERNATIONALIZATION HOWTO ----------------------------------------------------------------- - -this short howto explains how to use the internationalization -features of mir and how you can translate mir to other -languages. this is actually very easy: - - -* properties files (step 1) - -add a new file to the bundles/ directory. it should -be called exactly like the other files there, except -for the language code, which is the part after the underscore. -at the moment these files are called 'admin_XX.properties', so - -admin_de.properties contains the strings for the german language -admin_en.properties is the one for english. -admin.properties is always used as a fallback and contains imc -spcific information at the moment (this should probably change) - -the correct language code for your language can be found at -http://www.w3.org/WAI/ER/IG/ert/iso639.htm, for example. - - -* translation (step 2) - -the files just contain key and value pairs of the form -key=value. if a value contains something like {0}, {1}, and so -on, this means, that these placeholders are replaced when the -phrase is used. this is for example used for the key -show_from_to=showing from {0} to {1}. {0} and {1} get replaced -with the number of the first and the last record shown. - -in you new file (say admin_es.properties) you translate every key -into the appropriate phrase in your language. - - -* adding keys to templates - -you can define additional keys just by adding them to the -properties file and by referncing them in the freemaker template -with ${lang("keyname")}. you should do that every time you need -a language specific string! - - -* renaming keys - -some keys might not have a perfectly fitting name at the moment. -if you want to rename a key, please take care that you rename it -in ALL properties files and ALL templates. take care. - ----------------------------------------------------------------- -27.3.2002, br1 diff --git a/doc/KNOWN_BUGS b/doc/KNOWN_BUGS deleted file mode 100755 index 32ef7297..00000000 --- a/doc/KNOWN_BUGS +++ /dev/null @@ -1,24 +0,0 @@ -last changed: $Date: 2003/06/27 02:43:42 $ 2002 mir-coders -------------------------------------------------------------------- - -In all versions -=============== - -* the JAI library used for creating thumnails of images will often make the - thumbnail for a GIF or PNG image look like it has some television set snow in - it. The workaround would be to upload Jpeg images if you can. We are looking - into replacing JAI with another library. - Zapata: I fixed this (hopefully) - -* when deleting an item, be it an article or an uploaded media file, the action - will remove the data/meta-data from the DB and prevent it from show up in - lists, but it will not delete the file from the filesystem. hopefully this - will be fixed before 1.1.0 is released and in 1.0.1. (FIXME: is this still a - problem in the HEAD branch?) - Zapata: Deleting objects makes them untraceable and is thus generally a bad - idea. It can be so configured (using producers.xml) that hidden stuff (articles, - media) are deleted - -* some obscure "under certain conditions" corner cases listed in our bug tracker - at https://prod.indymedia.nl/mantis -* some others that I'm forgetting now. diff --git a/doc/LOCALIZER.HOWTO b/doc/LOCALIZER.HOWTO deleted file mode 100755 index 5fd51702..00000000 --- a/doc/LOCALIZER.HOWTO +++ /dev/null @@ -1,20 +0,0 @@ -Version: $Date: 2003/11/24 19:57:54 $ - -This is the HOWTO of the Localization infrastructure -which allows easy low-level customization of Mir. - - -1. Mir.Localizer - -In the file config.properties-dist -Mir.Localizer=mircoders.localizer.basic.MirBasicLocalizer - -JUST NOTES: - --Document how to enable your own CVS tree --Localizer code must be in etc/extrasource --build.xml is aware of etc/extrasource --contents of etc can be stored in extra cvs --which of etc is known to ant? --outside of etc nothing should be altered! --producers can be configured in config.properties diff --git a/doc/LONG.INSTALL.mir b/doc/LONG.INSTALL.mir deleted file mode 100755 index 7a0a0fcd..00000000 --- a/doc/LONG.INSTALL.mir +++ /dev/null @@ -1,537 +0,0 @@ -MIR INSTALLATION HOWTO - -Last updated: $Date: 2003/01/18 08:44:09 $ ----------------------------------------------------------------- - -Here is a short installation-howto of Mir, somewhat more explicit than -the earlier version. Some Debian-specific instructions are given. - - -prerequisites: - -- tomcat 4.0.4 (4.0.3 and below have some bad bugs) or above (3.3 works too as - of 04.04.2002, but this could change) - tomcat is available from http://jakarta.apache.org/tomcat/ -- apache 1.3.x. with mod_jk.so. As far as I can tell the connector for 2.x is - still rather undocumented. http://httpd.apache.org -- postgres 7.1.x or 7.2.x. http://www.postgresql.org -- ant (a java-based make) -- jaxp-1.1 (a SAX 2.0 compliant XML parser, comes with ant >= 1.4) -- the JAI image framework (Java Advanced Imaging) versin 1.1.1 . get it from - java.sun.com. ** NOTE: because JAI uses a native acceration library (a .so) - it must be placed in tomcat's "lib" (i.e $TOMCAT_HOME/common/lib) directory and - not under the default webapps/Mir/WEB-INF/lib directory ** -- A good reading of Tomcat, Apache and Postgresql documentation if you are not - familiar with any of them. The documentation is available at: - http://jakarta.apache.org/tomcat/tomcat-4.0-doc/index.html, - http://httpd.apache.org/docs/ and http://www.postgresql.org respectively. ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -0. To set all this up on Debian: - -make sure you have stable, testing, and unstable listings in -/etc/apt/sources.list. THen do all the following as root or using sudo! - -If you already have tomcat, and it's working well with apache, then -skip directly to (c). If it's not working well, then make sure you -purge _all_ conf files & so forth ( though it never hurts to back them -up first). "apt-get remove --purge" may not get rid of everything; try - -locate tomcat -and then delete all the files you find (again, if you're unsure what -they are, then back them up first). - - -(a) Install Java -apt-get install j2sdk1.3 j2sdk1.3-doc - -JAVA_HOME=/usr/lib/j2sdk1.3; export JAVA_HOME -PATH=$PATH:$JAVA_HOME/bin; export PATH -(add these lines to your .bashrc as well) - -(b) Installing Tomcat and Apache - -As root, do the following: -apt-get install apache - configure apache by editing httpd.conf: -* enable shtml includes: - - add LoadModule includes_module /usr/lib/apache/1.3/mod_include.so - - make sure your directory contains "Options Includes" -* Determine if you need to modify any apache mime-mappings - - The web-server host must recognize the .m3u, .pls and other file extensions - and send the proper "audio/x-mpegurl" and "audio/x-scpls" mime-types - respectively. If the web server is apache, it's easy, just - add: - - audio/x-mpegurl m3u - audio/x-scpl pls - - to the file pointed to by the "TypesConfig" command in your apache config - file. Or add and equivalent AddType command to your httpd.conf. Of course - this assumes that the mod_mime is loaded. -* Make sure that if you are using a non standard character set enconding that - Apache doesn't accidentally send the wrong encoding in the HTTP headers. - - - -Now deal with Tomcat: -apt-get install -t unstable tomcat4 tomcat4-webapps tomcat4-admin - --> this gets you tomcat4.1. You can work with tomcat 4.0.4 - as well, but a couple of specific configuration elements are - different. To get 4.0.4, run the following: - apt-get install -t testing tomcat4 tomcat4-webapps -apt-get install apachelib-java - -Tomcat will be installed in /usr/share/tomcat4, so you should put - -CATALINA_HOME=/usr/share/tomcat4; export CATALINA_HOME -TOMCAT_HOME=$CATALINA_HOME; export TOMCAT_HOME - -in your .bashrc; you might as well execute the ocmmand right now as -well. - -I found it somewhat difficult to get Tomcat and Apache working - together, until I emailed the Debian package maintainer, who told - me that he had purposely removed the mod_jk.conf-auto function from - Tomcat4.1! This is because Debian encourages Tomcat users to - switch to mod_webapp instead. You may want to try this option - out. I didn't, because I was able to get it working using the - JkMount option. So in /etc/apache/httpd.conf, look for a section - like this at the end: - - # The following line is for apacheconfig - DO NOT REMOVE! - JkWorkersFile /etc/tomcat/jk/workers.properties - Include /var/lib/tomcat/conf/mod_jk.conf - - - This has been insrted by libapache-java to try to get mod_jk to - work. unfortunately it doesn't work with Tomcat 4.1, so replace it - with the following: - - - # The following line is for apacheconfig - DO NOT REMOVE! - JkWorkersFile /etc/tomcat/jk/workers.properties - JkMount /*.jsp ajp13 - JkMount /Mir ajp13 - JkMount /Mir/* ajp13 - JkMount /servlet ajp13 - jkMount /examples/* ajp13 - #Include /var/lib/tomcat/conf/mod_jk.conf - -restart tomcat(as root): -/usr/share/tomcat4/bin/shutdown.sh -/usr/share/tomcat4/bin/startup.sh -restart apache(as root): -apachectl restart - -In your browser, check to see if each pogram is working on its own: -http://localhost should give you the debian apache start page -http://localhost:8180 should give you the tomcat start page - -now check to see if mod_jk is allowing the two programs to connect: -http://localhost/examples/servlets/index.html should give you the -Tomcat example servlets. - -Once this is working, you should enable the tomcat manager -application: -cd /usr/share/tomcat4/conf -open tomcat-users.xml in a text editor. Add a line like this: - - - -You should now be able to click on the "Manager" link on the Tomcat -home page, log in, and use the Manager functions. This is extremely -convenient when you're eloading Mir multiple times later on! - -(c) install postgres: -apt-get install postgresql postgresql-client postgresql-doc ---> the new postgres package should work fine with Mir. Make sure you -enable UNICODE, and if asked about JDBC (you shouldn't be) make sure -to enable it as well. if you would like to try a graphical frontend -for the database, find one using - -apt-cache show postgresql - -fmailiarize yourself with the psql interface, and the function of the -"postgres" user. - -(d) install JAI -go to: -http://java.sun.com/products/java-media/jai/downloads/download.html - -and download the "CLASSPATH for Linux" version of the JAI package -(1.1.01 works fine, later versions have not been tested by me) to -/usr/share/tomcat4/common/lib - -now: - -cd /usr/share/tomcat4/common/lib - -gunzip "name_of_file.tar.gz" (don't use the quotes: replace with the -real name of the file you downloaded!) - -tar -xvf "name_of_file.tar" - -read the instructions in -/usr/share/tomcat4/common/lib/jai_whatever_version_you_have/INSTALL-jai.txt - -Now add the JAI files to your CLASSPATH and LSD_LIBRARY_PATH: -JAIHOME=$TOMCAT_HOME/common/lib/jai-1_1_1_01/lib; export JAIHOME -CLASSPATH=$JAIHOME/jai_core.jar:$JAIHOME/jai_codec.jar:$JAIHOME/mlibwrapper_jai.jar:$CLASSPATH; -export CLASSPATH -LD_LIBRARY_PATH=.:$JAIHOME:$CLASSPATH; export LD_LIBRARY_PATH - ---> make sure to replace "jai-1_1_1_01" in the above with the -version-number of your copy of JAI ---> as above, it's a good idea to add these lines to your .bashrc - ---------------------------------------------------------------- - - -(1) CONFIGURE MIR! - -(a). get the latest version: - -cd to the directory where you would like to install the mir package - -cd /absolute/path - -CVS LOGIN: - - cvs -d :pserver:anonymous@mir.indymedia.org:/var/lib/cvs login - password: anonymous - -CVS CHECKOUT: - - cvs -d :pserver:anonymous@mir.indymedia.org:/var/lib/cvs co mir - - -(b) customize the config: - - cd mir/etc - cp config.properties-dist config.properties - -now customize config.properties for your needs. config.properties is -pretty well-documented, but read it carefully. I had to recompile -several times before I got all the pathnames right. - - -(c) configure the perms.sh file if neccessary -- IMPORTANT! READ THIS! -We provide a script that sets all files' and direcories' permissions to -a quite reasonable state. This script gets automagically called by -ant after compilationl. The most important thing you have to do after -compiling Mir is to ensure that the log files -- especially -dbentity.log -- are not readable by users that could compromise -system security, because all passwords and the like will be logged here. - - cp perms.sh-dist perms.sh - -Now, change the install directory and group in perms.sh - - edit perms.sh - - -(d) Customize the templates -you need to edit the templates before compiling, or not all of your -changes will show up in the produced site. If this is too -intimidating, don't worry -- you can always recompile! It only takes -about a minute... - -(e) check web.xml! ---> tomcat 4.1 has a different method of composing servlet URL's, so -if you are uasing 4.1, you wil need to make some minor changes to -mir/etc/web.xml - -look for sections like this: - - - Mir - - - /Mir - - - -the url-pattern has to change; so replace the above with: - - - Mir - - - /servlet/Mir - - -make sure to do the same for OpenMir and OutputMir. - - -------------------------------------------------------------- -------------------------------------------------------------- -IMPORTANT! It is a good idea to skip ahead to (2) and create the -Postgres database at this point. Then cd back to the mir directory, -and continue. -------------------------------------------------------------- -------------------------------------------------------------- - -(f) compile. Make sure all the environment variables are set as - indicated in section (0), or build.xml will not run properly: - -su -ant - - This should take about a minute. If you don't get an error, run - perms.sh: - sudo perms.sh - - -Do this as root so the permissions script is able to set -the permissions and owners correctly. - - -(g) Get Tomcat to recognize Mir. -Link in the webapps directory of tomcat to the install directory -(unless you changed the setting in config.properties, the -directory is called "Mir" and is located in the same directory in which -you installed the "mir" directory). (Here and in the rest of this document, -we assume you called the link "Mir", but this could be named anything.) - cd /path/to/tomcat/webapps (tomcat-4.0.x/webapps) - ln -s /path/to/Mir Mir - -dynamically reload Mir: - -http://localhost:8180/manager/stop?path=/Mir -if you're not using the Debian installation, you need to use: -http://localhost:8080/manager/stop?path=/Mir - -if you're using Tomcat 3.3, you need to restart Tomcat (consult the -docs for how to do that). - - -(h) Copy any dynamic library files ending with ".so" (so far only the JAI native -acceleration library found in the JAI package tarball or zip from sun) to your -$JAVA_HOME/jre/lib/i386 directory (where the other ".so" files live). Or, you -can skip the whole thing and live without "native" acceleration for image -manupulation. - -(2) CREATE AND CONLFIGURE THE MIR DATABASE! - -Review mir/etc/config.properties. Look carefully at the entries you -put in the DATABASE SETUP section, especially the Username, Password, -Host, and Name variables. If you don't know anything about Postgres, -look over the INSTALL.postgresql document, which is very helpful (but -remember, you don't need to install postgresql from scratch -anymore if you're on Debian woody!). Please do not use the "postgres" -user in config.properties -- this is a serious security risk. Choose -a username,a password, and a database name, then put those values in -config.properties if you haven't already. - -(a) Create the new database - -We create and configure the database as posgresql user "postgres": - - createdb -U postgres --encoding=unicode Mir ---> here and elsewhere, replace "Mir" with the name you already chose -for your database - - -(b) create an unprivileged database user for Mir -First, connect to the database as the database's superuser. - - psql -U postgres Mir - -Now we create the actual user. Please choose a password that is hard to -guess instead of "joshua". Good passwords have characters and numerals in -it, have no link to its owner (like being her birthday, age, name of her -husband, dog, child, car, favourite beer brand). A good password looks like -this: "8ncx4un". - - CREATE USER Mir WITH PASSWORD 'joshua' NOCREATEDB NOCREATEUSER; ---> again, don't just copy this into the psql command line -- replace -"Mir" and "joshua" with your username and password from config.properties - -now exit: -\q - - -(c) create base table -cd back to the mir home directory. now execute the following: - - psql -Upostgres -f dbscripts/create_pg.sql Mir -now quit psql: - \q -back in the shell, execute the dbscripts: - for i in dbscripts/help*.sql ; do psql -Upostgres -f $i Mir ; done - for i in dbscripts/populate*.sql ; do psql -Upostgres -f $i Mir ; done - -(d) Grant the required permissions to the new user -First, make your new user into the database administrator for the new -database (instead of postgres): -psql -U postgres Mir - select * from pg_database; - select * from pg_user; -you'll see a display like this: - usename | usesysid | usecreatedb | usetrace | usesuper | usecatupd | passwd | valuntil ---------------+----------+-------------+----------+----------+-----------+----------+---------- - postgres | 1 | t | t | t | t | ******** | - matt | 100 | t | f | t | t | ******** | - mir | 101 | f | f | f | f | ******** | - -followed by - - datname | datdba | encoding | datistemplate | datallowconn | datlastsysoid | datvacuumxid | datfrozenxid | datpath ------------+--------+----------+---------------+--------------+---------------+--------------+--------------+--------- - - template1 | 1 | 5 | t | t | 16554 | 11258 | 3221236731 | - - template0 | 1 | 5 | t | f | 16554 | 49 | 49 | - - Mir | 1 | 5 | f | t | 16554 | 10805 | 3221236278 | - -note the "usesysid" column for your new user, and the datname for your -new database. now execute the following line, obviousjly using the -variable you just noted: - -update pg_database set datdba=USESYSID_FROM_PG_USER where datname=DATABASENAME - -now exit psql: -\q - -save the following lines to a file called set.permissions: - -select 'grant all on '||relname||' to Mir;' -from pg_class -where relname not like 'pg%' -order by relname; - --->be sure to replace "Mir" with your username!!! - -(e) Apply neccessary changes to config.properties - ---> if you folowed the instructions above, you shouldn't have to do -this, but doublecheck! -Please open config.properties and look for the lines that begin with -"Database.". The interesting properties are "Username", "Password", "Host" -and "Name". Change these properties so that they reflect the settings you -used to create the database and the user. - -You should make sure that no copy of config.properties (neither in mir nor -in Mir/src nor in Mir/WEB-INF/classes nor in the directory tree you compiled -Mir from) is world-readable. Else you wouldn't have to install a password, -anyway. - -(f) Setup PostgreSQL so that all connections have to pass a password - -In /etc/postgresql/pg_hba.conf you should make sure that nobody can -use the database without a password, by inserting these lines: - -local all password -host all 127.0.0.1 255.0.0.0 password -host all 0.0.0.0 0.0.0.0 reject - -make sure you comment out all other permissions lines in this file! - -This means: All local connections (i.e. psql without "-h hostname" option) -have to authenticate themselves with a password. All connections from -localhost (127.0.0.1) have to supply a password, too. All other connections -are rejected. This line doen't have to be there if you have a properly -configured firewall but even if you do have one, it adds to the security in -case an attacker penetrates the firewall by some hack. - -If you can't access PostgreSQL after this for any reason, try and change -"password" in /etc/postgresql/pg_hba.conf to "trust". This should disable -any authentication method and make the database accessible again. Please use -this setting only temporarily because anybody who can access the PostgreSQL -server could take over the database completely this way. After you fixed -your password setting, switch the setting back to "password". -You may want to change your PostgreSQL password from time to time to make -database takeover harder. Rememer: Security is a process. - ----------------------------------------------------------------- - -AT THIS POINT YOU SHOULD HAVE A WORKING INSTAATION OF MIR! CHECK TO -MAKE SURE -- DON'T BOTHER WITH THE REST TILL YOIU'VE MADE MIR WORK ONCE! - - -Goodies: - -(3) Add the dupe prevention trigger to the database: - cd mir/dbscripts/dupetrigger - - There, read INSTALL and follow the instructions. - - -(4) Tweak mime-type extensions mappings in etc/web.xml file. - -*** Note the defaults should be o.k for most installations *** - -Add or remove any mime types you wish to support. This is used to figure -out the mime-type when (broken browsers?) browsers don't send the mime-type -in the content-type header field when uploading a media file. Note add the -moment you still have to add these to the media_type SQL table as well which -maps the mime-types to the correct mediaHandler class. See the comments in -the MirMedia class in javadoc for more details. - -11. restart tomcat - -13. configure apache - -edit http.conf: -* set the document root to the same directory as in the mir config file -* enable shtml includes: - - add LoadModule includes_module /usr/lib/apache/1.3/mod_include.so - - make sure your directory contains "Options Includes" -* Determine if you need to modify any apache mime-mappings - - The web-server host must recognize the .m3u, .pls and other file extensions - and send the proper "audio/x-mpegurl" and "audio/x-scpls" mime-types - respectively. If the web server is apache, it's easy, just - add: - - audio/x-mpegurl m3u - audio/x-scpl pls - - to the file pointed to by the "TypesConfig" command in your apache config - file. Or add and equivalent AddType command to your httpd.conf. Of course - this assumes that the mod_mime is loaded. - -that's it :) - -now the admin-application is accesable via: - - http://host/Mir/servlet/Mir - -and the openposting-servlet via - - http://host/Mir/servlet/OpenMir - -standard login is admin/indymedia. See the webdb_users SQL table to change/add -users or passwords. - - -SEARCHING - -The Mir code offers no internal search facilities, rather, the design -expects the use of an external program to crawl and index the static -site. One (recommended) tool for doing this is htdig -(http://htdig.org), which generates static databases of the site -content and then accesses those databases through a very fast CGI -program written in C. In the scripts directory, a perl CGI script -which wraps calls to htsearch is provided (scripts/search.pl) which -will allow searching based off of media type. (This is possible -because the standard templates will include META keywords like -hasAudio, hasVideo, etc.) - -UPGRADING - -see the UPGRADING.mir file. - -TROUBLESHOOTING - -You can give these a try if anything goes wrong: - -+ Restart Tomcat. Especially after compiling the sources Tomcat has to be - restarted. - -+ Check file permissions and ownership. Try and run perms.sh. - ----------------------------------------------------------------- - -$Date: 2003/01/18 08:44:09 $ - the Mir coders diff --git a/doc/README b/doc/README deleted file mode 100755 index 6ad2fb0d..00000000 --- a/doc/README +++ /dev/null @@ -1,88 +0,0 @@ -last changed $Date: 2003/11/24 19:57:54 $ ------------------------------------------ - -GENERAL INFO -============ - -Mir is an Open-Source java servlet based content managment system, designed to -run an indymedia(type) website. Besides powering several indymedia sites, a -number of progessive organizations use Mir customized for their own needs. Mir -aims to provide sophisticated functionality, for example, complete -multi-lingual content production, editing, administration, and presentation, -while retaining the ability to be run on less than top of the line hardware -through extensive static caching. - -Mir uses technologies such as Apache Tomcat and the Freemarker template engine. - -more info at: http://mir.indymedia.org - -development and general questions/discussion happens on the mir-coders mailing -list: mir-coders at lists.indymedia.org - -for archives or to subscribe: - -http://lists.indymedia.org/mailman/listinfo/mir-coders - -mailing list for cvs commits: - -http://lists.indymedia.org/mailman/listinfo/Mir-cvs - -LICENSING -========= - -Mir is licensed under the GNU GPL. - -FEATURES -======== - -* Static publishing: Mir produces static HTML files for easy mirroring and so - that the site can be viewed without creating a high load on servers. No fancy - caching mechanisms are necessary. The presentation and production are - completely independent from each other. -* Very configurable (see the config.properties file) -* Written in Java using standard servlet API and popular tools like those from - the Apache Jakarta project (http://jakarta.apache.org) -* Uses the Freemarker template engine to allow easy modification of - site design without programming knowledge. -* Structured Object oriented 4 layer design. Servlet modules, Entity/Database - (the persistance layer), Media handlers (an abstraction layer for - manipulating different media formats) and the Producer layer (for creating - the static html pages). see doc/CODESTRUCTURE for more details. -* The persistance layer uses the poolman package for caching Database - connections. -* Entity object caching is integrated into the persistance layer. -* Meta-data/Database schema and classification based on the Dublic Core - standard. Media folders, topics, features. -* supports displaying the dynamic part of the site in multiple languages using - the Java Locale/language bundle standard (.properties files). Bundles exist - for spanish, english, dutch, quechua, turkish, german and aymara. The - upcoming 1.1 version (in CVS) supports producing the static site in several - languages. -* Media abstraction layer to cleanly and easily handle/add different Media - formats like mp3, realmedia, video, etc.. uses mime-types to map to the - correct handler -* Supports categorization into topics and media folders (eg. different folders - for different events), features, breaking news, newswire, etc.. -* Production of xml RDF syndication. e.g for the indymedia global newswire. -* Powerful and rich admin/editor interface with features like the ability to - change the event date of an article, multiple ways to search.. help and much - more. -* Ability to edit some static site files such as CSS, html include files - through a basic web based text editor. -* Filtering of uploaded articles to remove unwanted HTML tags. -* Can output articles into PDF (upcoming 1.1 version has better text wrapping - support). -* Search via HTdig index of static files. (upcoming 1.1 CVS version uses - integrated Jakarta Lucene for indexing the static files.) -* Automatic thumbnail generation using Java Advanced Imaging (JAI). (1.1 will - probably use Jmagick) - -In the upcoming 1.1 release -=========================== - -* completely rewrite of the producer layer. Runs in it's own thread. - Configurable via an XML file to dynamically choose the structure the site - should take, what should be archived... -* Introduction of the Localization infrastructure to allow easy low-level - customization of Mir. - diff --git a/doc/README.jikes b/doc/README.jikes deleted file mode 100755 index c8523d48..00000000 --- a/doc/README.jikes +++ /dev/null @@ -1,5 +0,0 @@ -Last update: $Date: 2002/12/28 03:39:17 $ - -As of this writing the IBM Jikes compiler up to and including version 1.15 does -not work with mir. Jikes version 1.18 does work. We have not yet tested Jikes -V1.16 and V1.17. It is possible that they may work. diff --git a/doc/TODO.txt b/doc/TODO.txt deleted file mode 100755 index bd2d4f9f..00000000 --- a/doc/TODO.txt +++ /dev/null @@ -1,91 +0,0 @@ -[Updated $Date: 2002/12/23 05:38:50 $] - -v 1.1 - -* producers merged (done, max, mh) -* bundle cleanup (done, br1) -* new templates with css (done, thomas - max) -* seperation of things that should be edited and things that dont change: - admin templates in templates, producer templates in templates-dist? - (done, br1) -* utf8 encoding (mh) -* media refactoring (mh) -* index.en.html ,etc.. -* more formats for media uploads --> generic media upload support (mh) -* drop media_type table (mh) -* yet another search format what to do about it.. -* merge StringUtil/util *Routines stuff into one -* see for languages default --> merge it into OpenMir -* Throwable Vs. Exception -* merge MirConfig and config stuff in MirGlobal into one.. -* tuneup fileeditor -* producer queue job stop/start -* error reporting for Job queue? -* set config paramater for default timezone.. (for use in templates) - -before 2.0 - -* logging: log4j (max) --> is this not already a 1.1 item? -* configuration (mh, max) -* searching (john) --> is this not already a 1.1 item? -* HTML validation, struts (br1) -* PDF generation (john) -* better user interface (br1) -* split OpenPosting servlet modules or filter mechanism - - -v 2.0 - -* persistence layer: OJB or Torque (mh, idfx,...) -* data model -* struts (br1) -* users / roles (max) -* article translation - - -general - -* mir website maintainance -* website design / mir default templates -* documentation - - ---- misc --- - -c) Coverage: Alternative start-page for e.g. a event like genua. every article that has -something to do with this event can be seen on this page. (nn) -b) P2P-Data-Transfer/Content-Syndication: Implementing RDF/RSS-Support or a own -indymedia-protocoll. -drop media_type table -d) email-article-to-a-friend-servlet -e) semidynamic create-pdf-from-article-servlet: every requested pdf should be cached (underway, john) -f) servletapi-2.3: Filters for file upload (also in cos.jar) -g) servletapi-2.3: use web.xml for simpler/better error handling. -h) servletapi-2.3: set character encoding properly based on what the template says -i) servletapi-2.3: servletapi-2.3 requires tomcat-4.x, so require it -k) better transaction support in the DB/Persistance layer for more efficient -use of DB. -m) Editing producer-templates in the mir-servlet. (idfx) -n) Media infrastructure stuff: - - make a sort of Factory to get handler perhaps in EntiyMediaType - - MediaHandler should take care of storage tablename, the entry in SQL is - redundant. -> get rid of it - - maybe get rid of the MediaTypeTable entirely and have it in a config file? - - use FM's TemplateMethodModel to access the MediaHandler method in templates - instead of the crude way it's done now. - -*) move log to WEB-INF!!! (security problem) -*) - ---- wishlist --- - -* search engine: foto small thumbnails -* comments: mark last read comments -* comments: allow some HTML (let user choose) -* allow HTML in abstracts -* preview for video -* protection against spam - possibility to block submissions in case of spam attacks - apache: 1-2 postings / IP / minute - close artice for comments - image with password diff --git a/doc/UPGRADING.mir b/doc/UPGRADING.mir deleted file mode 100755 index 9dc325e9..00000000 --- a/doc/UPGRADING.mir +++ /dev/null @@ -1,29 +0,0 @@ -MIR UPGRADING HOWTO ----------------------------------------------------------------- - -For releases after 1.0.0-rc1, always check the NEWS file at the root of the -tree to check the [Notes] section to see what you might have to adjust. - -For non releases or releases before 1.0.0-rc1, aka. the latest sources from -CVS, it is a good idea to follow the advice below. - -Due to weaknesses of the current Mir configuration system, many folks get -bitten after doing an update of their cvs tree. Suddenly Mir starts throwing -weird exceptions, etc.. The cause is usually a new config option in the -source/config.properties-dist that is missing from your -source/config.properties file (the one that is actually used). - -a good way to check for this is to do the following (in the mir/ directory): - -cd source -diff -u config.properties config.properties-dist - -for this unfamiliar with the diff(1) program, you'll see a bunch of lines, some -starting with a "+" or "-". Look for a bunch of consecutive "+" symbols not -immeadiately followed by a "-". that usually is a new config option that you -should copy/paste (without the "+"'s of course) over to your existing -config.properties file and modify if necessary. - ----------------------------------------------------------------- - -last changed: $Date: 2002/12/07 07:00:16 $ - the Mir coders diff --git a/doc/mission.html b/doc/mission.html index c2b79561..97949ae0 100755 --- a/doc/mission.html +++ b/doc/mission.html @@ -1 +1,38 @@ -

mir developer mission statement


build creative free software that allows people to share and access content in an accesible way that promotes participation and is insensitive to repression, focussing to the needs of progressive grassroots organization.

mir key features:

  • cms(content management system) implemented in the java programming language with an emphasis on design and structure.
  • simplicity of mirroring content.
  • production system  of the cms is independent of publication system location and type
  • support for multiple languages, media types and publication means
  • implements a wide range of content submission, approval and publication models without the need to alter the underlying code, from complete open posting to total editorial control
\ No newline at end of file + + + + Mir mission statement + + + +

mir developer mission statement

+ +

+ build creative free software that allows people to + share and access content in an accesible way that + promotes participation and is insensitive to + repression, focussing to the needs of progressive + grassroots organization. +

+ +

mir key features:

+
    +
  • cms(content management system) implemented in the + java programming language with an emphasis on design + and structure.
  • + +
  • simplicity of mirroring content.
  • + +
  • production system  of the cms is independent + of publication system location and type
  • + +
  • support for multiple languages, media types and + publication means
  • + +
  • implements a wide range of content submission, + approval and publication models without the need to + alter the underlying code, from complete open posting + to total editorial control
  • +
+ + \ No newline at end of file diff --git a/etc/bundles/adminlocal.properties b/etc/bundles/adminlocal.properties index a8b60451..7395e489 100755 --- a/etc/bundles/adminlocal.properties +++ b/etc/bundles/adminlocal.properties @@ -1,2 +1,3 @@ # put your own local admin properties in this file # (like for custom article types) + diff --git a/etc/bundles/open_en.properties b/etc/bundles/open_en.properties index 2937f00c..97ed4a0e 100755 --- a/etc/bundles/open_en.properties +++ b/etc/bundles/open_en.properties @@ -6,6 +6,8 @@ langcode=en optional=optional required=required +general.unexpectederror=An unexpected error has occurred + posting.htmltitle=Mir | open posting posting.step00= Step 00 @@ -44,11 +46,13 @@ posting.phone=your telephone number posting.language=the language of your article posting.text=your article posting.text.info=fill in the text of your article here +posting.media.ftpmedia = FTP uploads (please enter the filename) posting.media=media posting.media.info=upload media-files (supported are jpg|gif|mp3|avi|qt|mpeg) max size: 20 Mb posting.media.howto=(Press "Browse" and select the file you want to upload) posting.media.media=Media posting.media.title=media sub-title +posting.media.cancel=Cancel posting.submit.info=Please press submit only once!
It will appear in a few minutes on the main page. It might even take longer in case of technical problems. posting.criteria= posting.submit=Submit (patience is a virtue!) @@ -56,7 +60,7 @@ posting.reset=Form Reset posting.error.missingpassword=The one-time password must be copied into the password field posting.error.invalidpassword=The one-time password was not copied correctly into the password field posting.error.missingfield=At least one field was not correctly entered -media.error.unsupportedformat=The format of the media you uploaded is not supported +media.error.unsupportedformat=The format of the media you uploaded ({0}) is not supported postingdone.htmltitle=open posting postingdone.title=You have successfully submitted your article diff --git a/etc/config.properties-dist b/etc/config.properties-dist index 0b16d91f..a3a1970a 100755 --- a/etc/config.properties-dist +++ b/etc/config.properties-dist @@ -18,21 +18,22 @@ # d) database config # # edit this to suit your needs -# After you edited this file, "ant" has to be invoked. -# To be sure, also restart Tomcat. +# After editing this file, two steps need to be taken to make the changes effective: +# 1. ant has to be invoked. +# 2. tomcat needs to be restarted. # -# Note that for Mir to work, Tomcat has to be set up to handle all -# URLs that begin with /servlet. All other URLs are handled by Apache. +# This file only contains the properties that are most often changed. To view all +# possible config values, refer to the file default.properties, located in the +# source directory. Don't change settings in default.properties however, instead +# use this file. # -# There are more configuration values located in the default.properties file -# located in source/. If necessary these values can be overridden in this file. +# Note: for filename values, by default, files are used relative to the servlet's +# WEB-INF directory. # # The setup uses the following assumptions: -# The URL to reach the site is http://mir.code-fu.org +# The URL to reach the site is http://mir.someserver.org # The StorageRoot of this URL is /var/www/project/site/ # All produced pages and media are located below this directory. -# The servlets are also found there in a /servlet subdir. - ################################################ ############ A) GENERAL SETUP ############## @@ -53,14 +54,6 @@ Mir.Tech-email.name=mir-admins mailinglist Mir.Public-email.address=project@somemailserver.org Mir.Public-email.name=project mailinglist - -# DirectOpenposting -# yes = articles appear in the newswire on the startpage directly after posting them -# no = new articles not in newswire by default -# and editors have to promote them before they show on startpage -# -DirectOpenposting=yes - # Default timezone to display times in in admin, producers # use CET for Central European Time (Paris, Amsterdam) # more timezones here: http://www.postgresql.org/docs/7.2/static/timezones.html @@ -68,46 +61,14 @@ DirectOpenposting=yes Mir.DefaultTimezone= UTC # Default date/time format -# +# For the syntax of the format, refer to +# http://java.sun.com/j2se/1.3/docs/api/java/text/SimpleDateFormat.html Mir.DefaultDateTimeFormat = yyyy-MM-dd HH:mm -# where to put the lucene index -# for the build in searchengine -# (must be created by you and writable by tomcat-user) -# -IndexPath=/var/www/project/lucineindex - -# temp-dir used for media-uploads -# -TempDir=/tmp - -# Logging -# by default logs are found in bin/mir/WEB-INF/log -# -Log.LogClass = mir.log.log4j.LoggerImpl -Log.log4j.ConfigurationFile = etc/log4j.properties -Log.Home = log - -# Mir.Localizer -# for your additional site-specific java-code -# -Mir.Localizer=mircoders.localizer.basic.MirBasicLocalizer - -# The location of the producer specifiations -# -Mir.Localizer.ProducerConfigFile=etc/producer/producers.xml - # For missing values, the FallbackLanguage is used as default # Mir.Admin.FallbackLanguage=en -# the templates -# -Mir.Localizer.Producer.GeneratorLibrary= default=freemarker(etc/producer/) -Mir.Localizer.Admin.GeneratorLibrary= default=freemarker(templates/admin/) -Mir.Localizer.OpenPosting.GeneratorLibrary= default=freemarker(etc/open/) - - ################################# # admin interface configuration # ################################# @@ -123,36 +84,11 @@ Mir.Login.Languages=en;de;fr;nl;es;pt;eu;sv;tr;zh;gz # Mir.Admin.ShowLoggedinUsers=1 -# How should the custom operations (hide etc) in article and comment lists -# be presented? -# 0 = links, 1 = checkboxes, 2 = a listbox -# -Mir.Localizer.Admin.ListOperationsFlavor=1 - -# How should the topics be presented on the article edit page? -# 0 = in a multiselect list box, 1 = checkboxes -# -Mir.Localizer.Admin.TopicListFlavor=1 - -# For the checkboxes flavour, how many columns should there be? -# -Mir.Localizer.Admin.TopicListColumns=3 - -# In which order should the topic appear? -# -Mir.Localizer.Admin.TopicListOrder=title - # enable deletion of comments/articles? # Mir.Localizer.Admin.AllowDeleteComment=1 Mir.Localizer.Admin.AllowDeleteArticle=1 -# Article Preview Link URL (Link to produced articles from within admin) -# -Article.PublicUrl=http://mir.code-foo.org/en/${to_content.date.formatted.yyyy}/${to_content.date.formatted.MM}/${to_content.id}.shtml -Comment.PublicUrl=http://mir.code-foo.org/en/${date.formatted.yyyy}/${date.formatted.MM}/${id}.shtml - - ####################### # automated producers # ####################### @@ -196,9 +132,6 @@ Rsync.Script.Path=/var/www/bin/rsync-copy.sh ServletModule.FileEdit.Configuration= \ includes:/var/www/project/site/includes:.*\\.inc:1 - - - ################################################ ########### B) STATIC SITE CONFIG ############# ################################################ @@ -206,13 +139,13 @@ ServletModule.FileEdit.Configuration= \ # the url of the static site # on the machine where mir runs on # -Producer.ProductionHost=http://mir.code-fu.org +Producer.ProductionHost=http://mir.someserver.org # the url of the public site # only different from ProductionHost if pages are copied to # one ore more mirror-servers for delivery # -Producer.PublicationHost=http://mir.code-fu.org +Producer.PublicationHost=http://mir.someserver.org # Produrce.StorageRoot is the directory, in which # the generated HTML pages will be stored @@ -236,19 +169,19 @@ Producer.DocRoot= # the url of the video-server # -Producer.Video.Host=http://mir.code-fu.org/video +Producer.Video.Host=http://mir.someserver.org/video # the url of the audio-server # -Producer.Audio.Host=http://mir.code-fu.org/audio +Producer.Audio.Host=http://mir.someserver.org/audio # the url of the image-server # -Producer.Image.Host=http://mir.code-fu.org/images +Producer.Image.Host=http://mir.someserver.org/images # the url of the media-server # -Producer.Media.Host=http://mir.code-fu.org/media +Producer.Media.Host=http://mir.someserver.org/media # the url of the real-media-server # @@ -328,7 +261,7 @@ Producer.ActionServlet=/servlet/Mir # the url of the openposting-servlet # -Producer.OpenAction=http://mir.code-fu.org/servlet/OpenMir +Producer.OpenAction=http://mir.someserver.org/servlet/OpenMir # the maximum allowed size of an uploaded media file in KB. # @@ -343,7 +276,6 @@ ServletModule.OpenIndy.MaxMediaUploadItems=20 ServletModule.OpenIndy.DefaultMediaUploadItems=1 - ###################### # PDF configurations # ###################### @@ -370,17 +302,6 @@ PDF.Footer=Mir-CMS PDF-Newsletter. Content is good, and free to use for non-com # PDF.PageSize=A4 - -#the style sheet used to turn html into xsl:fo -#this is not currently in use, so don't worry about it -Producer.HTML2FOStyleSheet=/some/dir/mir/etc/producer/html2fo.xsl - - - -###################################################################### -# edit with caution below this line -###################################################################### - ################################################ ############ D) DATABASE CONFIG ############## ################################################ @@ -393,29 +314,16 @@ Database.Password= Database.Host=localhost Database.Port=5432 - -Database.poolMin=1 -Database.poolMax=10 -Database.poolResetTime=1.0 -Database.PoolLog=log/pool.log -Database.Limit=20 Database.Driver=org.postgresql.Driver - ############################################ -# servlet / module encoding configurations # +# encoding configuration # ############################################ -# don't change this unless you really know your i18n. # The default encoding charset used in the written html files as well # as the dynamic output html. -# also used for the HTML charset meta tag. -# -Mir.DefaultEncoding=UTF8 - -# this encoding is used for the HTML charset meta tag. -# it must be the html charset equivalent of the Java encoding above -# don't change this unless... -# Mir.DefaultHTMLCharset=UTF-8 + +# The java equivalent of Mir.DefaultHTMLCharset +Mir.DefaultEncoding=UTF8 diff --git a/etc/content-types.properties b/etc/content-types.properties deleted file mode 100755 index e3c4407b..00000000 --- a/etc/content-types.properties +++ /dev/null @@ -1,285 +0,0 @@ -#sun.net.www MIME content-types table; version 1.6, 05/04/99 -# -# Property fields: -# -# ::= 'description' '=' -# ::= 'file_extensions' '=' -# ::= 'icon' '=' -# ::= 'browser' | 'application' | 'save' | 'unknown' -# ::= 'application' '=' -# - -# -# The "we don't know anything about this data" type(s). -# Used internally to mark unrecognized types. -# -content/unknown: description=Unknown Content -unknown/unknown: description=Unknown Data Type - -# -# The template we should use for temporary files when launching an application -# to view a document of given type. -# -temp.file.template: /tmp/%s - -# -# The "real" types. -# -application/octet-stream: \ - description=Generic Binary Stream;\ - file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz - -application/oda: \ - description=ODA Document;\ - file_extensions=.oda - -application/pdf: \ - description=Adobe PDF Format;\ - file_extensions=.pdf - -application/postscript: \ - description=Postscript File;\ - file_extensions=.eps,.ai,.ps;\ - icon=ps;\ - action=application;\ - application=imagetool %s - -application/x-dvi: \ - description=TeX DVI File;\ - file_extensions=.dvi;\ - action=application;\ - application=xdvi %s - -application/x-hdf: \ - description=Hierarchical Data Format;\ - file_extensions=.hdf;\ - action=save - -application/x-latex: \ - description=LaTeX Source;\ - file_extensions=.latex - -application/x-netcdf: \ - description=Unidata netCDF Data Format;\ - file_extensions=.nc,.cdf;\ - action=save - -application/x-tex: \ - description=TeX Source;\ - file_extensions=.tex - -application/x-texinfo: \ - description=Gnu Texinfo;\ - file_extensions=.texinfo,.texi - -application/x-troff: \ - description=Troff Source;\ - file_extensions=.t,.tr,.roff;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff %s | col | more -w\" - -application/x-troff-man: \ - description=Troff Manpage Source;\ - file_extensions=.man;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\" - -application/x-troff-me: \ - description=Troff ME Macros;\ - file_extensions=.me;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\" - -application/x-troff-ms: \ - description=Troff MS Macros;\ - file_extensions=.ms;\ - action=application;\ - application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\" - -application/x-wais-source: \ - description=Wais Source;\ - file_extensions=.src,.wsrc - -application/zip: \ - description=Zip File;\ - file_extensions=.zip;\ - icon=zip;\ - action=save - -application/x-bcpio: \ - description=Old Binary CPIO Archive;\ - file_extensions=.bcpio; action=save - -application/x-cpio: \ - description=Unix CPIO Archive;\ - file_extensions=.cpio; action=save - -application/x-gtar: \ - description=Gnu Tar Archive;\ - file_extensions=.gtar;\ - icon=tar;\ - action=save - -application/x-shar: \ - description=Shell Archive;\ - file_extensions=.sh,.shar;\ - action=save - -application/x-sv4cpio: \ - description=SVR4 CPIO Archive;\ - file_extensions=.sv4cpio; action=save - -application/x-sv4crc: \ - description=SVR4 CPIO with CRC;\ - file_extensions=.sv4crc; action=save - -application/x-tar: \ - description=Tar Archive;\ - file_extensions=.tar;\ - icon=tar;\ - action=save - -application/x-ustar: \ - description=US Tar Archive;\ - file_extensions=.ustar;\ - action=save - -audio/basic: \ - description=Basic Audio;\ - file_extensions=.snd,.au;\ - icon=audio;\ - action=application;\ - application=audiotool %s - -audio/x-aiff: \ - description=Audio Interchange Format File;\ - file_extensions=.aifc,.aif,.aiff;\ - icon=aiff - -audio/x-wav: \ - description=Wav Audio;\ - file_extensions=.wav;\ - icon=wav - -image/gif: \ - description=GIF Image;\ - file_extensions=.gif;\ - icon=gif;\ - action=browser - -image/ief: \ - description=Image Exchange Format;\ - file_extensions=.ief - -image/jpeg: \ - description=JPEG Image;\ - file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\ - icon=jpeg;\ - action=browser;\ - application=imagetool %s - -image/tiff: \ - description=TIFF Image;\ - file_extensions=.tif,.tiff;\ - icon=tiff - -image/vnd.fpx: \ - description=FlashPix Image;\ - file_extensions=.fpx,.fpix - -image/x-cmu-rast: \ - description=CMU Raster Image;\ - file_extensions=.ras - -image/x-portable-anymap: \ - description=PBM Anymap Format;\ - file_extensions=.pnm - -image/x-portable-bitmap: \ - description=PBM Bitmap Format;\ - file_extensions=.pbm - -image/x-portable-graymap: \ - description=PBM Graymap Format;\ - file_extensions=.pgm - -image/x-portable-pixmap: \ - description=PBM Pixmap Format;\ - file_extensions=.ppm - -image/x-rgb: \ - description=RGB Image;\ - file_extensions=.rgb - -image/x-xbitmap: \ - description=X Bitmap Image;\ - file_extensions=.xbm,.xpm - -image/x-xwindowdump: \ - description=X Window Dump Image;\ - file_extensions=.xwd - -image/png: \ - description=PNG Image;\ - file_extensions=.png;\ - icon=png;\ - action=browser - -text/html: \ - description=HTML Document;\ - file_extensions=.htm,.html;\ - icon=html - -text/plain: \ - description=Plain Text;\ - file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\ - icon=text;\ - action=browser - -text/tab-separated-values: \ - description=Tab Separated Values Text;\ - file_extensions=.tsv - -text/x-setext: \ - description=Structure Enhanced Text;\ - file_extensions=.etx - -video/mpeg: \ - description=MPEG Video Clip;\ - file_extensions=.mpg,.mpe,.mpeg;\ - icon=mpeg;\ - action=application;\ - application=mpeg_play %s - -video/quicktime: \ - description=QuickTime Video Clip;\ - file_extensions=.mov,.qt - -application/x-troff-msvideo: \ - description=AVI Video;\ - file_extensions=.avi;\ - icon=avi - -video/x-sgi-movie: \ - description=SGI Movie;\ - file_extensions=.movie,.mv - -message/rfc822: \ - description=Internet Email Message;\ - file_extensions=.mime - -application/xml: \ - description=XML document;\ - file_extensions=.xml - -audio/mp3: \ - description=MPEG Layer 3;\ - file_extensions=.mp3;\ - icon=mpeg;\ - action=application;\ - application=mpg123 %s - -audio/vnd.rn-realaudio: \ - description=RealAudio File;\ - file_extensions=.ra - diff --git a/etc/extralib/README b/etc/extralib/README new file mode 100755 index 00000000..d43e611e --- /dev/null +++ b/etc/extralib/README @@ -0,0 +1 @@ +This directory is for local jar files. diff --git a/etc/log4j.properties b/etc/log4j.properties index 136953b8..ea73b3fb 100755 --- a/etc/log4j.properties +++ b/etc/log4j.properties @@ -81,7 +81,7 @@ log4j.appender.GlobalA.layout=org.apache.log4j.PatternLayout log4j.appender.GlobalA.layout.ConversionPattern=%d [%p] %c %x %m%n log4j.appender.UtilityA=org.apache.log4j.RollingFileAppender -log4j.appender.UtilityA.File=${log.home}/global.log +log4j.appender.UtilityA.File=${log.home}/utility.log log4j.appender.UtilityA.layout=org.apache.log4j.PatternLayout log4j.appender.UtilityA.layout.ConversionPattern=%d [%p] %c %x %m%n diff --git a/etc/open/comment.template b/etc/open/comment.template deleted file mode 100755 index cd693b86..00000000 --- a/etc/open/comment.template +++ /dev/null @@ -1,132 +0,0 @@ - - - ${lang("comment.htmltitle")} - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ${lang("comment.header")} -
-

- - ${lang("comment.note")} - -
- ${data.passwd} -
-
-

- -
- ${lang("comment.formtitle")} -
${lang("comment.password")}:
- ${lang("comment.title")}: - - (${lang("required")}) -
- ${lang("comment.name")}: - - (${lang("required")}) -
- ${lang("comment.email")}: - - (${lang("optional")}) -
- ${lang("comment.url")}: - - (${lang("optional")}) -
- ${lang("comment.phone")}: - - (${lang("optional")}) -
- ${lang("comment.address")}: - - (${lang("optional")}) -
- ${lang("comment.language")}: - - - (${lang("optional")}) -
- ${lang("comment.text")}: - -   -

-
  - -
-  
- -
-
-  
- -
-
- -
- - - diff --git a/etc/open/comment_done.template b/etc/open/comment_done.template deleted file mode 100755 index 0b7ebf68..00000000 --- a/etc/open/comment_done.template +++ /dev/null @@ -1,37 +0,0 @@ - - - - - ${lang("commentdone.htmltitle")} - - - - - - - - - - - - - -
- ${lang("commentdone.thanks")} -
- -
- ${lang("commentdone.wait")} -
- ${lang("commentdone.criteria")} -
- ${lang("commentdone.stay_calm")}
-
- -
- >> ${lang("commentdone.back")} -
- - - diff --git a/etc/open/comment_dupe.template b/etc/open/comment_dupe.template deleted file mode 100755 index 3f44874a..00000000 --- a/etc/open/comment_dupe.template +++ /dev/null @@ -1,37 +0,0 @@ - - - - - ${lang("commentdupe.htmltitle")} - - - - - - - - - - - - - -
- - ${lang("commentdupe.title")} - -
- -
- ${lang("commentdupe.explanation")} -
-
${lang("commentdupe.no_panic")}

-
-
-
- >> ${lang("commentdupe.back")} -
- - - diff --git a/etc/open/donetranslation.template b/etc/open/donetranslation.template new file mode 100755 index 00000000..5041125a --- /dev/null +++ b/etc/open/donetranslation.template @@ -0,0 +1,55 @@ + + + + + ${lang("postingdone.htmltitle")} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+   start >> + + ${lang("translation.donetitle")} +  
 
  +
+ ${lang("translationdone.info")}
+
+ ${lang("commentdone.stay_calm")}
+
+
 
  + + ${lang("postingdone.back")} >> + +  
 

+ + + + diff --git a/etc/open/editarticle.template b/etc/open/editarticle.template index 4cbeba2c..5bd19d75 100755 --- a/etc/open/editarticle.template +++ b/etc/open/editarticle.template @@ -2,16 +2,7 @@ ${lang("posting.htmltitle")} - - - - - - - - - - + + + + + + + + + + + +function to display error message at the input box // occam, 2003-06-09 + + + + +${lang(e.message + "." + e.field)} + + + + + + + + + Your input had the following errors:

+ + + + ${lang("content."+e.field)}: + + ${lang(e.message)}
+
+
+ + +
+ + + + +
+ +
+ +
+ +
+ +

+${lang("translation.form.title")} +

+
+ + +

${lang("posting.errors")}

+
+ + + +

+${lang("translation.step01")} +

+ +
+ +

+${lang("translation.language")} +

+ +
+${lang("translation.to_language.other")} + + + +

+${lang("translation.author")} +

+ + + + +(${lang("required")}) + +
+ + +

+${lang("translation.step02")} +

+
+ +

+${lang("translation.title")} +

+

${utility.encodeHTML(parent.title)}

+

+ + + + +

+ + + +

+${lang("translation.abstract")} +

+

${utility.encodeHTML(parent.description)}

+ + + + + +

+${lang("translation.text")} +

+

${utility.encodeHTML(parent.content_data)}

+ + + + +

+${lang("translation.is_html")} +

+ + + +
+ +

+${lang("translation.step03")} +

+
+ +

+${lang("translation.submit.info")} +

+
+ + +
+ +
+ +
+
+ + diff --git a/etc/open/error.template b/etc/open/error.template index 6965788a..b4e01c30 100755 --- a/etc/open/error.template +++ b/etc/open/error.template @@ -20,7 +20,7 @@

-

${data.date} -- ${data.errorstring} +

${errorstring}

diff --git a/etc/open/posting.template b/etc/open/posting.template deleted file mode 100755 index 6d35bee8..00000000 --- a/etc/open/posting.template +++ /dev/null @@ -1,234 +0,0 @@ - - - - ${lang("posting.htmltitle")} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- >> ${lang("posting.jump_to_form")} -
-
- ${lang("posting.title")}
-
- - - - -
${data.passwd} -
-

- -
${lang("posting.nr_of_media")}
- ${lang("posting.nr_of_media.info")}
  -
-
${lang("posting.form.title")}
-
${lang("posting.password")}
- ${lang("posting.title")}:
- ${lang("posting.title.info")} -
-
(${lang("required")})
-
- ${lang("posting.topic")}:
- ${lang("posting.topic.info")} -
- -   (${lang("optional")}) -
- ${lang("posting.author")}: - -
${lang("required")}
-
- ${lang("posting.abstract")}:
- ${lang("posting.abstract.info")} -
- -
${lang("posting.abstract.constraint")}
-
- - ${lang("posting.contact.info")} - -
- ${lang("posting.email")}: - -
- (${lang("optional")}) -
- ${lang("posting.url")}: - -
- (${lang("optional")}) -
- ${lang("posting.address")}: - -
- (${lang("optional")}) -
- ${lang("posting.phone")}: - -
- (${lang("optional")}) -
 
- ${lang("posting.language")}: - - -   (${lang("optional")}) -
- ${lang("posting.text")}:
- ${lang("posting.text.info")} -
-   -

-
- ${lang("posting.media")}: - - ${lang("posting.media.info")}
- ${lang("posting.media.howto")} -
- ${lang("posting.media.title")} ${m}: - -
-
${lang("posting.media.media")} ${m} - -
(${lang("optional")}) -
 
- - - ${lang("posting.submit.info")} - -
- ${lang("posting.criteria")}
- -
- - - - -
- - - - - diff --git a/etc/open/posting_done.template b/etc/open/posting_done.template deleted file mode 100755 index baee9ee9..00000000 --- a/etc/open/posting_done.template +++ /dev/null @@ -1,35 +0,0 @@ - - - - - ${lang("postingdone.htmltitle")} - - - - - - - - - - - - - - - -
- ${lang("postingdone.title")}
- - -
-${lang("postingdone.info")} -

-
${lang("postingdone.stay_calm")}


- -
-
- >> ${lang("postingdone.back")} -
- - diff --git a/etc/open/posting_dupe.template b/etc/open/posting_dupe.template deleted file mode 100755 index e5329e35..00000000 --- a/etc/open/posting_dupe.template +++ /dev/null @@ -1,37 +0,0 @@ - - - - - ${lang("postingdupe.htmltitle")} - - - - - - - - - - - - - -
- - ${lang("postingdupe.title")} - -
- -
- ${lang("postingdupe.explanation")} -
-
${lang("postingdupe.no_panic")}

-
-
-
- >> ${lang("postingdupe.back")} -
- - - diff --git a/etc/open/prepare_mail.template b/etc/open/preparemail.template similarity index 67% rename from etc/open/prepare_mail.template rename to etc/open/preparemail.template index a5446baa..74f2e2b2 100755 --- a/etc/open/prepare_mail.template +++ b/etc/open/preparemail.template @@ -15,17 +15,16 @@ ${lang("email.prepare.description")}
-

- - -${lang("email.prepare.sendtowhom")}
-${lang("email.prepare.from.email")}
-${lang("email.prepare.from.name")}
-${lang("email.prepare.comment")}
+ + +${lang("email.prepare.sendtowhom")}
+${lang("email.prepare.from.email")}
+${lang("email.prepare.from.name")}
+${lang("email.prepare.comment")}
${lang("email.prepare.chooselanguage")} diff --git a/etc/open/search_results.template b/etc/open/search_results.template index 1a416e80..01e42d48 100755 --- a/etc/open/search_results.template +++ b/etc/open/search_results.template @@ -182,11 +182,9 @@ ${lang("search.sort_how")}   -
-
  diff --git a/etc/open/sessionerror.template b/etc/open/sessionerror.template index 6965788a..9a7081a0 100755 --- a/etc/open/sessionerror.template +++ b/etc/open/sessionerror.template @@ -4,7 +4,6 @@ - @@ -32,6 +31,5 @@
@@ -20,7 +19,7 @@

-

${data.date} -- ${data.errorstring} +

${errorstring}

- diff --git a/etc/open/unsupportedmediatype.template b/etc/open/unsupportedmediatype.template index 6965788a..5e8bcac0 100755 --- a/etc/open/unsupportedmediatype.template +++ b/etc/open/unsupportedmediatype.template @@ -14,13 +14,8 @@ -

${lang("error.text", config["Mir.Tech-email.address"], config["Mir.Tech-email.name"])} - - - -

-

${data.date} -- ${data.errorstring} +

${lang("media.error.unsupportedformat", mimetype)}

diff --git a/etc/producer/RSS-full.template b/etc/producer/RSS-full.template new file mode 100755 index 00000000..be4f4df4 --- /dev/null +++ b/etc/producer/RSS-full.template @@ -0,0 +1,97 @@ + + + + + + ${title}width="${w}" height="${h}"> +
${title}
+
+ + + + + + + + + + + + + + ${utility.encodeHTML(channeltitle)} + ${utility.encodeHTML(channelidentifier)} + + ${utility.encodeHTML(channeldescription)} + + + ${utility.encodeHTML(channelpublisher)} + + Open Content License, http://www.opencontent.org + ${config.now.formatted.dc} + + + + + + + + + + + + ${utility.encodeHTML(i.title)} + ${articleprefix}/${i.date.formatted["yyyy"]}/${i.date.formatted["MM"]}/${i.id}.shtml + ${utility.encodeHTML(i.description_parsed)} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ]]> + ${utility.encodeHTML(i.content_data_parsed)} +
+ ${i.creationdate.formatted["yyyy-MM-dd'T'HH:mm'-07:00'"]} + + ${utility.encodeHTML(i.creator)} + + + ${utility.encodeXML(i.creator_main_url)} + + ${i.language.code} +
+
+
diff --git a/etc/producer/RSS.template b/etc/producer/RSS.template index 89017b30..0be5075a 100755 --- a/etc/producer/RSS.template +++ b/etc/producer/RSS.template @@ -9,26 +9,25 @@ ${utility.encodeXML(channeltitle)} - ${utility.encodeXML(channellink)} + ${utility.encodeXML(channelidentifier)} ${utility.encodeXML(channeldescription)} ${utility.encodeXML(channelpublisher)} Open Content License, http://www.opencontent.org - ${config.now.dc} + ${config.now.formatted.dc} - - + + - - - ${i.title} - ${config["Producer.ProductionHost"]}${config.docRoot}${i.publish_path}${i.id}.shtml - ${i.description_sentence} - ${i.webdb_create_dc}+0200 + + + ${i.title} + ${articleprefix}/${i.date.formatted["yyyy"]}/${i.date.formatted["MM"]}/${i.id}.shtml + ${i.creationdate.formatted["yyyy-MM-dd'T'HH:mm'-07:00'"]} diff --git a/etc/producer/article.template b/etc/producer/article.template index 8c862abb..68986c11 100755 --- a/etc/producer/article.template +++ b/etc/producer/article.template @@ -107,16 +107,24 @@
+
+   +
+
+
+  ${lang("general.addtranslation")} >> +
+

${article.title}

-

${article.creator}, ${article.creationdate.formatted["dd.MM.yyyy HH:mm"]}

+

${article.to_original.creator} (${lang("general.translatedby", article.creator)}), ${article.to_original.creationdate.formatted["dd.MM.yyyy HH:mm"]}


${article.description_parsed}

- + - +

  @@ -125,7 +133,7 @@

- +

@@ -133,7 +141,7 @@

- +

@@ -141,7 +149,7 @@

- +


-   +   ${lang("article.addcomment")} >>
- +
- +
${utility.encodeHTML(c.title)}
${c.creationdate.formatted["dd.MM.yyyy - HH:mm"]}
diff --git a/etc/producer/featurearchive.template b/etc/producer/featurearchive.template index febb8bf3..5133f195 100755 --- a/etc/producer/featurearchive.template +++ b/etc/producer/featurearchive.template @@ -76,30 +76,37 @@

- + + + + + + + +

${i.title}
- ${i.creator}, ${i.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

+ ${aorig.creator} (${lang("general.translatedby", i.creator)}), ${aorig.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_other[0]["big_icon"]}"> - + ${i.to_media_images[0][ + src="${aorig.to_media_images[0]["icon_path"]}" + width="${aorig.to_media_images[0]["icon_width"]}" + height="${aorig.to_media_images[0]["icon_height"]}" + border=0 alt="${aorig.to_media_images[0]["title"]}"> ${i.description_parsed}
diff --git a/etc/producer/languagebar.template b/etc/producer/languagebar.template new file mode 100755 index 00000000..000b3dcf --- /dev/null +++ b/etc/producer/languagebar.template @@ -0,0 +1,4 @@ +${article.to_original.languagename} + + | ${a.languagename} + diff --git a/etc/producer/navigation.template b/etc/producer/navigation.template index b55b4c26..f359e169 100755 --- a/etc/producer/navigation.template +++ b/etc/producer/navigation.template @@ -42,4 +42,20 @@


- +
+ ${lang("navigation.syndication")}
+ + XML ${lang("syndication.features")}
+ XML ${lang("syndication.features")} ${lang("syndication.full")}
+ XML ${lang("syndication.newswire")}
+ XML ${lang("syndication.newswire")} ${lang("syndication.full")}
+
+ + XML ${t.title} ${lang("syndication.features")}
+ XML ${t.title} ${lang("syndication.features")} ${lang("syndication.full")}
+ XML ${t.title} ${lang("syndication.newswire")}
+ XML ${t.title} ${lang("syndication.newswire")} ${lang("syndication.full")}
+
+
+
+
diff --git a/etc/producer/newswirearchive.template b/etc/producer/newswirearchive.template index 5031978e..0cca4af3 100755 --- a/etc/producer/newswirearchive.template +++ b/etc/producer/newswirearchive.template @@ -76,30 +76,38 @@
- + + + + + + + + +

${i.title}
- ${i.creator}, ${i.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

+ ${aorig.creator} (${lang("general.translatedby", i.creator)}), ${aorig.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_other[0]["big_icon"]}"> - + ${i.to_media_images[0][ + src="${aorig.to_media_images[0]["icon_path"]}" + width="${aorig.to_media_images[0]["icon_width"]}" + height="${aorig.to_media_images[0]["icon_height"]}" + border=0 alt="${aorig.to_media_images[0]["title"]}"> ${i.description_parsed}
diff --git a/etc/producer/producers.xml b/etc/producer/producers.xml index 4311a74b..9b0bbd6b 100755 --- a/etc/producer/producers.xml +++ b/etc/producer/producers.xml @@ -13,7 +13,7 @@ - + @@ -23,10 +23,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -47,34 +141,52 @@ + + + + + + + + + + + + + + + + - - - + @@ -345,6 +457,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/producer/radicalendar.template b/etc/producer/radicalendar.template new file mode 100755 index 00000000..8d6ca171 --- /dev/null +++ b/etc/producer/radicalendar.template @@ -0,0 +1,5 @@ +

    + +
  • ${c.eventdate} ${c.title} ${c.eventtime}
    ${c.description} + +
diff --git a/etc/producer/routines.template b/etc/producer/routines.template index 750dcebd..ce639bf1 100755 --- a/etc/producer/routines.template +++ b/etc/producer/routines.template @@ -1,107 +1,107 @@ - - This file contains several routines to be used in the templates - - - - ${aText} - - - - ${utility.encodeHTML(aText)} - - - - - - - ${aDefault} - - + + This file contains several routines to be used in the templates + + + + ${aText} + + + + ${utility.encodeHTML(aText)} + + + + + + + ${aDefault} + + ${aText} - - - - -
-
- - - - - -
- - -
-
- - - - - -
- - -
-
- - - - - -
- - -
-
- ${image[
- -
- -
- - + + + + +
+
+ + + - + +
+ + +
+
+ + + - + +
+ + +
+
+ + + - + +
+ + +
+
+ ${image[
+ +
+ +
+ + - + - + - + ${anArticle.to_media_images[0][ - - - + + +

, ${anArticle.creationdate.formatted["dd.MM.yyyy HH:mm"]}

- ${anArticle.description_parsed} + ${anArticle.description_parsed}

- +

[]

-
- - - + + + + ${anArticle.to_media_icon["icon_alt"]} - + src="${anArticle.to_media_icon["tiny_icon"]}" width="12"> +
${n.creationdate.formatted["dd-MM-yyyy HH:mm"]}
-
- +
+ diff --git a/etc/producer/startpage.template b/etc/producer/startpage.template index 8f2e841c..afdd74b4 100755 --- a/etc/producer/startpage.template +++ b/etc/producer/startpage.template @@ -101,31 +101,38 @@ - -
+ + + + + + + + +

${s.title}
- ${s.creator}, ${s.creationdate.formatted["dd.MM.yyyy - HH:mm"]}

+ ${sorig.creator} (${lang("general.translatedby", s.creator)}), ${sorig.creationdate.formatted["dd.MM.yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_other[0]["big_icon"]}"> - + ${s.to_media_images[0][ + src="${sorig.to_media_images[0]["icon_path"]}" + width="${sorig.to_media_images[0]["icon_width"]}" + height="${sorig.to_media_images[0]["icon_height"]}" + border=0 alt="${sorig.to_media_images[0]["title"]}"> ${s.description_parsed}
@@ -138,30 +145,37 @@ - + + + + + + + +

${i.title}
- ${i.creator}, ${i.creationdate.formatted["dd.MM.yyyy - HH:mm"]}

+ ${forig.creator} (${lang("general.translatedby", i.creator)}), ${forig.creationdate.formatted["dd.MM.yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${forig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${forig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${forig.to_media_other[0]["big_icon"]}"> - + ${i.to_media_images[0][ + src="${forig.to_media_images[0]["icon_path"]}" + width="${forig.to_media_images[0]["icon_width"]}" + height="${forig.to_media_images[0]["icon_height"]}" + border=0 alt="${forig.to_media_images[0]["title"]}"> ${i.description_parsed}
@@ -187,8 +201,16 @@ - - ${n.to_media_icon.icon_alt} + + + + + + + + + + ${norig.to_media_icon.icon_alt} ${n.title}
${n.creationdate.formatted["dd-MM-yyyy HH:mm"]}
diff --git a/etc/producer/topicpage.template b/etc/producer/topicpage.template index ed357e0a..d30b89fd 100755 --- a/etc/producer/topicpage.template +++ b/etc/producer/topicpage.template @@ -82,31 +82,38 @@
- + + + + + + + + " + + " " + + "bla die bla >" + + " ", new MirExpressionParser()); + } + else { + return parser.parse("hoi", new MirExpressionParser()); + } + } + catch (Throwable t) { + t.printStackTrace(); + System.out.println(t.toString()); + return null; + } + } + }; + + Map test = new HashMap(); + + Template template = library.lookupTemplate("a"); + + PrintWriter p = new PrintWriter(System.out); + + template.process(new HashMap(), p, new TALLogger.TALSystemOutLogger(), library); + + p.close(); + + } + catch (Throwable t) { + System.out.println("Exception: " + t.toString()); + t.printStackTrace(System.out); + } + } + public static void main2(String args[]) { + try { + TALTemplateEngine engine = new TALTemplateEngine( + new MirExpressionParser(), new File("m:/romania/mir/etc/producer/")); Map test = new HashMap(); test.put("name", "zapata"); - TALTemplate template = engine.loadTemplate("frame.template"); + Template template = engine.loadTemplate("indy-ro-txt.html"); PrintWriter p = new PrintWriter(System.out); - template.processTemplate(new Object(), p, new TALLogger.TALSystemOutLogger()); + template.process(new Object(), p, new TALLogger.TALSystemOutLogger(), engine); p.close(); diff --git a/source/mir/generator/tal/interfaces/TALExpressionParser.java b/source/mir/generator/tal/interfaces/TALExpressionParser.java index c8f6d45b..bc3106e9 100755 --- a/source/mir/generator/tal/interfaces/TALExpressionParser.java +++ b/source/mir/generator/tal/interfaces/TALExpressionParser.java @@ -50,20 +50,20 @@ public interface TALExpressionParser { /** * process a direct assignment of an object to a preparsed reference expression * - * @param aContext - * @param aPreparsedReferenceExpression - * @param aValue */ public void processDirectAssignment(Object aContext, Object aPreparsedReferenceExpression, Object aValue); - /** * process an assigment to a pseudo variable. The pseudo variable will have a java * identifier-like name. * - * @param aContext - * @param aPreparsedReferenceExpression - * @param aValue */ public void processPseudoAssignment(Object aContext, String aName, Object aValue); + + /** + * Retrieve the value of a pseudo variable + * + */ + public Object evaluatePseudoVariable(Object aContext, String aName); + } \ No newline at end of file diff --git a/source/mir/generator/tal/template/CompositeTemplateNode.java b/source/mir/generator/tal/template/CompositeTemplateNode.java index fc2b7146..55a6cb0a 100755 --- a/source/mir/generator/tal/template/CompositeTemplateNode.java +++ b/source/mir/generator/tal/template/CompositeTemplateNode.java @@ -29,30 +29,53 @@ */ package mir.generator.tal.template; -import java.util.List; -import java.util.Vector; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import java.util.Map; import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.interfaces.TALLogger; -import mir.generator.tal.template.PlainTextTemplateNode; -public class CompositeTemplateNode - implements TemplateNode { +/** + * Template node that is composed of a list of template nodes. + * + */ +public class CompositeTemplateNode implements TemplateNode { private List parts; public CompositeTemplateNode() { - parts = new Vector(); + parts = new ArrayList(); } - public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException { + /** {@inheritDoc} */ + public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, + TALLogger aLogger, Map aTemplateContext, TemplateLibrary aLibrary) throws TemplateProcessingException { Iterator i = parts.iterator(); while (i.hasNext()) { - ((TemplateNode) i.next()).process(aParser, aContext, aDestination, aLogger); + ((TemplateNode) i.next()).process(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); + } + } + + public String getPlainText() { + StringBuffer result = new StringBuffer(); + + Iterator i = parts.iterator(); + while (i.hasNext()) { + result.append(((TemplateNode) i.next()).getPlainText()); } + + return result.toString(); } + public boolean isEmpty() { + return parts.isEmpty(); + } + + /** + * Adds a TemplateNode at the end of the chain. + */ public void appendSubNode(TemplateNode aNode) { if (aNode instanceof CompositeTemplateNode) { Iterator i = ((CompositeTemplateNode) aNode).parts.iterator(); @@ -60,13 +83,16 @@ public class CompositeTemplateNode appendSubNode((TemplateNode) i.next()); } } - else if (aNode instanceof PlainTextTemplateNode && parts.size()>0 && + else if (aNode instanceof PlainTextTemplateNode && + parts.size()>0 && (parts.get(parts.size()-1) instanceof PlainTextTemplateNode)) { ((PlainTextTemplateNode) parts.get(parts.size()-1)).appendText(((PlainTextTemplateNode) aNode).getText()); + ((PlainTextTemplateNode) parts.get(parts.size()-1)).appendPlainText(((PlainTextTemplateNode) aNode).getPlainText()); } else { parts.add(aNode); } } + } diff --git a/source/mir/generator/tal/template/TALBasicTemplateNodeLibrary.java b/source/mir/generator/tal/template/CoreTemplateNodeLibrary.java similarity index 70% rename from source/mir/generator/tal/template/TALBasicTemplateNodeLibrary.java rename to source/mir/generator/tal/template/CoreTemplateNodeLibrary.java index fbb1f456..e806deb9 100755 --- a/source/mir/generator/tal/template/TALBasicTemplateNodeLibrary.java +++ b/source/mir/generator/tal/template/CoreTemplateNodeLibrary.java @@ -30,11 +30,7 @@ package mir.generator.tal.template; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.Vector; -import java.util.Iterator; +import java.util.*; import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.interfaces.TALLogger; @@ -44,7 +40,7 @@ import mir.util.xml.XMLName; import mir.util.xml.XMLParserExc; import mir.util.xml.XMLReaderTool; -public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { +public class CoreTemplateNodeLibrary implements TemplateNodeLibrary { private String prefix; private String uri; @@ -52,7 +48,7 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI()); } - public TALBasicTemplateNodeLibrary(String aPrefix, String aUri) { + public CoreTemplateNodeLibrary(String aPrefix, String aUri) { prefix = aPrefix; uri = aUri; } @@ -66,7 +62,8 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { private static final String OMITTAG_ATTRIBUTE = "omit-tag"; private static final String ATTRIBUTE_ATTRIBUTE = "attributes"; - public TemplateNode constructTemplateNode(TALExpressionParser aParser, XMLName aTag, Map anAttributes, TemplateNode aChildTemplateNode) throws XMLParserExc { + public TemplateNode constructTemplateNode(TALExpressionParser aParser, XMLName aTag, Map anAttributes, + TemplateNode aChildTemplateNode, Map aTemplateContext) throws XMLParserExc { TALBasicTemplateNode result = new TALBasicTemplateNode(XMLReaderTool.normalizeXMLName(aTag)); result.setBody(aChildTemplateNode); @@ -127,7 +124,7 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { Iterator j = attributes.iterator(); while (j.hasNext()) { String value = (String) j.next(); - List parts = StringRoutines.separateString(value, " "); + List parts = StringRoutines.separateString(value.trim(), " "); if (parts.size()==2) { result.addModifiedAttribute((String) parts.get(0), aParser.preparseExpression((String) parts.get(1))); @@ -165,7 +162,7 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { fixedAttributes = new HashMap(); attributeModifiers = new HashMap(); - definitions = new Vector(); + definitions = new ArrayList(); condition = null; repeatVariable = null; @@ -231,18 +228,21 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { } } - public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException { + public void process(TALExpressionParser aParser, Object aContext, + StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext, + TemplateLibrary aLibrary) throws TemplateProcessingException { if (errorExpression != null) { StringBuffer destination = new StringBuffer(); try { - outerProcess(aParser, aContext, aDestination, aLogger); + outerProcess(aParser, aContext, destination, aLogger, aTemplateContext, aLibrary); } catch (Throwable t) { try { - destination.delete(0, destination.length()); +// destination.delete(0, destination.length()); aParser.processPseudoAssignment(aContext, "exception", t); - destination.append(aParser.evaluateStringExpression(aContext, errorExpression)); + destination.insert(0, aParser.evaluateStringExpression(aContext, errorExpression)); + destination.append(" >>>ERROR POSITION<<< "); } catch (Throwable s) { throw new TemplateProcessingException(s); @@ -253,43 +253,69 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { } } else { - outerProcess(aParser, aContext, aDestination, aLogger); + outerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); } } - public void outerProcess(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException { - Iterator i; + public String getPlainText() { + return body.getPlainText(); + } - i = definitions.iterator(); - while (i.hasNext()) { - Definition d = (Definition) i.next(); - aParser.processAssignment(aContext, d.getVariable(), d.getExpression()); - } + public void outerProcess(TALExpressionParser aParser, Object aContext, + StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext, + TemplateLibrary aLibrary) throws TemplateProcessingException { + + Object oldAttributes = aParser.evaluatePseudoVariable(aContext, "tagattributes"); + aParser.processPseudoAssignment(aContext, "tagattributes", Collections.unmodifiableMap(fixedAttributes)); + + Object oldContent = aParser.evaluatePseudoVariable(aContext, "tagcontent"); + aParser.processPseudoAssignment(aContext, "tagcontent", body.getPlainText()); + + try { + Iterator i; + + i = definitions.iterator(); + while (i.hasNext()) { + Definition d = (Definition) i.next(); + aParser.processAssignment(aContext, d.getVariable(), d.getExpression()); + } - if (condition == null || aParser.evaluateBooleanExpression(aContext, condition)) { - if (repeatExpression != null) { - i = aParser.evaluateListExpression(aContext, repeatExpression); + if (condition == null || aParser.evaluateBooleanExpression(aContext, condition)) { + if (repeatExpression != null) { + i = aParser.evaluateListExpression(aContext, repeatExpression); - while (i.hasNext()) { - aParser.processDirectAssignment(aContext, repeatVariable, i.next()); - innerProcess(aParser, aContext, aDestination, aLogger); + while (i.hasNext()) { + aParser.processDirectAssignment(aContext, repeatVariable, i.next()); + innerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); + } + } + else { + innerProcess(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); } } - else { - innerProcess(aParser, aContext, aDestination, aLogger); + } + finally { + try { + aParser.processPseudoAssignment(aContext, "tagattributes", oldAttributes); + aParser.processPseudoAssignment(aContext, "tagcontent", oldContent); + } + catch (Throwable t) { } } }; - private void innerProcess(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) + private void innerProcess(TALExpressionParser aParser, Object aContext, + StringBuffer aDestination, TALLogger aLogger, Map aTemplateContext, TemplateLibrary aLibrary) throws TemplateProcessingException { boolean omitTag = false; + StringBuffer content = aDestination; if (omitTagExpression != null) omitTag = aParser.evaluateBooleanExpression(aContext, omitTagExpression); if (!omitTag) { + content = new StringBuffer(); Map generatedAttributes = new HashMap(fixedAttributes); Iterator i = attributeModifiers.entrySet().iterator(); @@ -312,21 +338,42 @@ public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary { aDestination.append(HTMLRoutines.encodeHTML( (String) entry.getValue())); aDestination.append("\""); } - aDestination.append(">"); } - if (contentExpression != null) { - aDestination.append(aParser.evaluateStringExpression(aContext, contentExpression)); - } - else { - if (body != null) { - body.process(aParser, aContext, aDestination, aLogger); + try{ + if (contentExpression != null) { + content.append(aParser.evaluateStringExpression(aContext, contentExpression)); + } + else { + if (body != null) { + body.process(aParser, aContext, content, aLogger, aTemplateContext, aLibrary); + } + } + if (!omitTag) { + if (content.length()==0) { + aDestination.append(" />"); + } + else { + aDestination.append(">"); + aDestination.append(content); + aDestination.append(""); + } } } - if (!omitTag) { - aDestination.append(""); + catch (Throwable t) { + if (!omitTag) { + aDestination.append(content); + } + + if (t instanceof TemplateProcessingException) { + throw (TemplateProcessingException) t; + } + else if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + else throw new TemplateProcessingException(t.toString()); } } } diff --git a/source/mir/generator/tal/template/MacroTemplateNodeLibrary.java b/source/mir/generator/tal/template/MacroTemplateNodeLibrary.java new file mode 100755 index 00000000..1310c7ba --- /dev/null +++ b/source/mir/generator/tal/template/MacroTemplateNodeLibrary.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.generator.tal.template; + +import java.util.Map; +import java.util.Iterator; +import java.util.List; +import java.util.HashMap; + +import mir.generator.tal.interfaces.TALExpressionParser; +import mir.generator.tal.interfaces.TALLogger; +import mir.util.xml.XMLName; +import mir.util.xml.XMLParserExc; +import mir.util.xml.XMLReaderTool; +import mir.util.StringRoutines; +import mir.util.HTMLRoutines; + +public class MacroTemplateNodeLibrary implements TemplateNodeLibrary { + /** {@inheritDoc} */ + private static final String DEFINE_MACRO_ATTRIBUTE = "define-macro"; + private static final String USE_MACRO_ATTRIBUTE = "use-macro"; + private static final String DEFINE_SLOT_ATTRIBUTE = "define-slot"; + private static final String FILL_SLOT_ATTRIBUTE = "fill-macro"; + + public static final String MACRO_DEFINITIONS_KEY = "$" + MacroTemplateNodeLibrary.class.getName() + "$macro_definitions"; + public static final String ORPHANED_SLOTS_KEY = "$" + MacroTemplateNodeLibrary.class.getName() + "$macro_definitions"; + + private String prefix; + private String uri; + + + private boolean isOurTag(XMLName aName) { + return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI()); + } + + public MacroTemplateNodeLibrary(String aPrefix, String aUri) { + prefix = aPrefix; + uri = aUri; + } + + public TemplateNode constructTemplateNode(TALExpressionParser anExpressionParser, XMLName aTag, Map anAttributes, + TemplateNode aChildTemplateNode, Map aTemplateContext) throws XMLParserExc { + + StringBuffer prefix = new StringBuffer(); + boolean useSurroundingTag = !(isOurTag(aTag)); + + prefix.append("<").append(XMLReaderTool.normalizeXMLName(aTag)); + String suffix = ""; + + String macroDefinition = null; + String slotDefinition = null; + String slotFill = null; + Object macroCallExpression = null; + + Iterator i = anAttributes.entrySet().iterator(); + + while (i.hasNext()) { + Map.Entry entry = (Map.Entry) i.next(); + XMLName name = (XMLName) entry.getKey(); + + if (!isOurTag(name)) { + prefix.append(" ").append(XMLReaderTool.normalizeXMLName(name)); + prefix.append("=\"").append(HTMLRoutines.encodeHTML( (String) entry.getValue())).append('"'); + } + else { + if (name.getLocalName().equalsIgnoreCase(DEFINE_MACRO_ATTRIBUTE)) { + macroDefinition = (String) entry.getValue(); + } + else if (name.getLocalName().equalsIgnoreCase(USE_MACRO_ATTRIBUTE)) { + macroCallExpression = anExpressionParser.preparseStringExpression((String) entry.getValue()); + } + else if (name.getLocalName().equalsIgnoreCase(DEFINE_SLOT_ATTRIBUTE)) { + slotDefinition = (String) entry.getValue(); + } + else if (name.getLocalName().equalsIgnoreCase(FILL_SLOT_ATTRIBUTE)) { + slotFill = (String) entry.getValue(); + } + } + } + prefix.append(">"); + + MacroTemplateNode result; + if (useSurroundingTag) { + result = new MacroTemplateNode(aChildTemplateNode, prefix.toString(), suffix, slotDefinition, slotFill); + } + else { + result = new MacroTemplateNode(aChildTemplateNode, "", "", slotDefinition, slotFill); + } + + if (macroCallExpression!=null) { + result.setMacroCall(macroCallExpression); + } + + if (macroDefinition!=null) { + macroDefinition = macroDefinition.trim(); + if (macroDefinition.length()==0) { + throw new XMLParserExc("Empty macro name"); + } + + Map definitions = (Map) aTemplateContext.get(MACRO_DEFINITIONS_KEY); + if (definitions==null) { + definitions=new HashMap(); + aTemplateContext.put(MACRO_DEFINITIONS_KEY, definitions); + } + + if (definitions.containsKey(macroDefinition)) { + throw new XMLParserExc("Duplicate macro name: " + macroDefinition); + } + + definitions.put(macroDefinition, result); + + Map slots = (Map) aTemplateContext.get(ORPHANED_SLOTS_KEY); + if (slots!=null) { + } + } + + return result; + } + + private class MacroTemplateNode implements TemplateNode { + private TemplateNode childNode; + private String prefix; + private String suffix; + + private Object macroCallTemplateExpression = null; + + private String slotDefinition; + private String slotFill; + + public MacroTemplateNode(TemplateNode aChildNode, String aPrefix, String aSuffix, + String aSlotDefinition, String aSlotFill) { + childNode = aChildNode; + prefix = aPrefix; + suffix = aSuffix; + + slotDefinition = aSlotDefinition; + slotFill = aSlotFill; + } + + public void setMacroCall(Object anExpression) { + macroCallTemplateExpression = anExpression; + } + + /** {@inheritDoc} */ + public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, + TALLogger aLogger, Map aTemplateContext, TemplateLibrary aLibrary) throws TemplateProcessingException { + + if (macroCallTemplateExpression!=null) { + String macroPath = aParser.evaluateStringExpression(aContext, macroCallTemplateExpression); + List parts = StringRoutines.separateString(macroPath, "#"); + if (parts.size()!=2) { + throw new TemplateProcessingException("Invalid macro path '" + macroPath + "'"); + } + + Template template = aLibrary.lookupTemplate((String) parts.get(0)); + Map definitions = (Map) template.getContext().get(MACRO_DEFINITIONS_KEY); + if (template==null) { + throw new TemplateProcessingException("Cannot find template '" + (String) parts.get(0) + "'"); + } + if (definitions==null || !definitions.containsKey(parts.get(1))) { + throw new TemplateProcessingException("No macro '"+(String) parts.get(1)+"' found in template '" + (String) parts.get(0) + "'"); + } + + MacroTemplateNode macro = (MacroTemplateNode) definitions.get(parts.get(1)); + + macro.process(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); + } + else { + aDestination.append(prefix); + + childNode.process(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary); + aDestination.append(suffix); + } + } + + public String getPlainText() { + return childNode.getPlainText(); + } + } +} diff --git a/source/mir/generator/tal/template/PlainTextTemplateNode.java b/source/mir/generator/tal/template/PlainTextTemplateNode.java index 85da0865..617d45d2 100755 --- a/source/mir/generator/tal/template/PlainTextTemplateNode.java +++ b/source/mir/generator/tal/template/PlainTextTemplateNode.java @@ -29,30 +29,49 @@ */ package mir.generator.tal.template; +import java.util.Map; + import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.interfaces.TALLogger; -public class PlainTextTemplateNode - implements TemplateNode { - private String text; +/** + * Simple TemplateNode that just outputs a fixed + * piece of allText. + */ +public class PlainTextTemplateNode implements TemplateNode { + private String allText; + private String plainText; public PlainTextTemplateNode() { - this(""); + this("", ""); } - public PlainTextTemplateNode(String aText) { - text = aText; + public PlainTextTemplateNode(String aText, String aPlainText) { + allText = aText; + plainText = aPlainText; } + /** Appends text at the end */ public void appendText(String aText) { - text = text + aText; + allText = allText + aText; + } + + /** Appends allText at the end */ + public void appendPlainText(String aText) { + plainText = plainText + aText; + } + + public String getText() { + return allText; } - protected String getText() { - return text; + public String getPlainText() { + return plainText; } - public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException { - aDestination.append(text); + public void process(TALExpressionParser aParser, Object aContext, + StringBuffer aDestination, TALLogger aLogger, + Map aTemplateContext, TemplateLibrary aLibrary) throws TemplateProcessingException { + aDestination.append(allText); } } diff --git a/source/mir/generator/tal/template/TALTemplate.java b/source/mir/generator/tal/template/Template.java similarity index 75% rename from source/mir/generator/tal/template/TALTemplate.java rename to source/mir/generator/tal/template/Template.java index eb56e41e..e890c054 100755 --- a/source/mir/generator/tal/template/TALTemplate.java +++ b/source/mir/generator/tal/template/Template.java @@ -30,38 +30,38 @@ package mir.generator.tal.template; import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.Vector; import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.interfaces.TALLogger; -import mir.util.HTMLRoutines; /** - * - * - * * @see TAL Spec */ -public class TALTemplate { +public class Template { private TemplateNode rootNode; private TALExpressionParser parser; + private Map context; - public TALTemplate(TALExpressionParser aParser, TemplateNode aRootNode) { + public Template(TALExpressionParser aParser, TemplateNode aRootNode, Map aTemplateContext) { rootNode = aRootNode; parser = aParser; + context = aTemplateContext; + } + + /** get this template's context */ + public Map getContext() { + return context; } - public void processTemplate(Object aContext, PrintWriter aDestination, TALLogger aLogger) throws TemplateProcessingException { + public void process(Object aContext, PrintWriter aDestination, + TALLogger aLogger, TemplateLibrary aLibrary) throws TemplateProcessingException { StringBuffer output = new StringBuffer(); - aLogger.debug("TALTemplate", "processing rootnode"); - rootNode.process(parser, aContext, output, aLogger); - aLogger.debug("TALTemplate", "done processing rootnode"); + aLogger.debug("Template", "processing rootnode"); + rootNode.process(parser, aContext, output, aLogger, context, aLibrary); + aLogger.debug("Template", "done processing rootnode"); aDestination.print(output); } diff --git a/source/mir/generator/tal/template/TemplateLibrary.java b/source/mir/generator/tal/template/TemplateLibrary.java new file mode 100755 index 00000000..e558c890 --- /dev/null +++ b/source/mir/generator/tal/template/TemplateLibrary.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.generator.tal.template; + +/** + * A TemplateLibrary offers access to a set of {@link Template}s. + * Templates can be looked up by name. + */ +public interface TemplateLibrary { + /** + * Looks up a Template based on a name + */ + public Template lookupTemplate(String aTemplateName) throws TemplateProcessingException; +} diff --git a/source/mir/generator/tal/template/TemplateNode.java b/source/mir/generator/tal/template/TemplateNode.java index 9b622156..824552d1 100755 --- a/source/mir/generator/tal/template/TemplateNode.java +++ b/source/mir/generator/tal/template/TemplateNode.java @@ -29,9 +29,24 @@ */ package mir.generator.tal.template; +import java.util.Map; + import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.interfaces.TALLogger; +/** + * A {@link Template} consists of a chain of TemplateNodes. + */ public interface TemplateNode { - public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException; + /** + */ + public void process( + TALExpressionParser aParser, + Object aContext, + StringBuffer aDestination, + TALLogger aLogger, + Map aTemplateContext, + TemplateLibrary aTemplateLibrary) throws TemplateProcessingException; + + public String getPlainText(); } diff --git a/source/mir/generator/tal/template/TALTemplateNodeLibrary.java b/source/mir/generator/tal/template/TemplateNodeLibrary.java similarity index 80% rename from source/mir/generator/tal/template/TALTemplateNodeLibrary.java rename to source/mir/generator/tal/template/TemplateNodeLibrary.java index 2d1aab82..bdb85459 100755 --- a/source/mir/generator/tal/template/TALTemplateNodeLibrary.java +++ b/source/mir/generator/tal/template/TemplateNodeLibrary.java @@ -35,6 +35,15 @@ import mir.util.xml.XMLName; import mir.util.xml.XMLParserExc; import mir.generator.tal.interfaces.TALExpressionParser; -public interface TALTemplateNodeLibrary { - public TemplateNode constructTemplateNode(TALExpressionParser anExpressionParser, XMLName aTag, Map anAttributes, TemplateNode aChildTemplateNode) throws XMLParserExc; +public interface TemplateNodeLibrary { + /** + * Construct a {@link TemplateNode} based on the tag and attributes given. + * + * @param anExpressionParser + * @param aTag + * @param anAttributes + * @param aChildTemplateNode + */ + public TemplateNode constructTemplateNode(TALExpressionParser anExpressionParser, + XMLName aTag, Map anAttributes, TemplateNode aChildTemplateNode, Map aTemplateContext) throws XMLParserExc; } diff --git a/source/mir/generator/tal/template/TemplateNodeLibraryRegistry.java b/source/mir/generator/tal/template/TemplateNodeLibraryRegistry.java new file mode 100755 index 00000000..a67e371e --- /dev/null +++ b/source/mir/generator/tal/template/TemplateNodeLibraryRegistry.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.generator.tal.template; + +public interface TemplateNodeLibraryRegistry { + public TemplateNodeLibrary findLibraryForUrl(String aUrl); + public TemplateNodeLibrary findLibraryForPrefix(String aPrefix); +} diff --git a/source/mir/generator/tal/template/TemplateProcessingException.java b/source/mir/generator/tal/template/TemplateProcessingException.java index da7bb1b0..19a70b43 100755 --- a/source/mir/generator/tal/template/TemplateProcessingException.java +++ b/source/mir/generator/tal/template/TemplateProcessingException.java @@ -45,4 +45,8 @@ public class TemplateProcessingException extends Exception { public TemplateProcessingException(String aMessage) { this(aMessage, null); } + + public Throwable getCause() { + return cause; + } } diff --git a/source/mir/log/Logger.java b/source/mir/log/Logger.java index 47dc7db9..46d052a2 100755 --- a/source/mir/log/Logger.java +++ b/source/mir/log/Logger.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ @@ -38,4 +38,6 @@ public interface Logger { public void warn( Object o, String s); public void error( Object o, String s); public void fatal( Object o, String s); + + public void reload() throws LoggerExc, LoggerFailure; } diff --git a/source/mir/log/Log.java b/source/mir/log/LoggerEngine.java similarity index 73% rename from source/mir/log/Log.java rename to source/mir/log/LoggerEngine.java index 17fec303..9073595c 100755 --- a/source/mir/log/Log.java +++ b/source/mir/log/LoggerEngine.java @@ -18,65 +18,64 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.log; import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; -public class Log { - - private static Logger myLogger; +public class LoggerEngine { + private static Logger loggerInstance; static { try { String loggerClass = MirPropertiesConfiguration.instance().getString("Log.LogClass"); - myLogger = (Logger) Class.forName(loggerClass).newInstance(); + loggerInstance = (Logger) Class.forName(loggerClass).newInstance(); } catch (java.lang.ClassNotFoundException cnfe) { - System.err.println("Log was not able to initialize: class not found"); + System.err.println("LoggerEngine was not able to initialize: class not found"); cnfe.printStackTrace(System.err); } catch (java.lang.InstantiationException ie) { System.err.println( - "Log was not able to initialize: could not initialize class"); + "LoggerEngine was not able to initialize: could not initialize class"); ie.printStackTrace(System.err); } catch (java.lang.IllegalAccessException iae) { - System.err.println("Log was not able to initialize: illegal access"); + System.err.println("LoggerEngine was not able to initialize: illegal access"); iae.printStackTrace(System.err); } - catch (PropertiesConfigExc e) { - e.printStackTrace(System.err); - } } public static void debug(Object o, String s) { - myLogger.debug(o, s); + loggerInstance.debug(o, s); } public static void info(Object o, String s) { - myLogger.info(o, s); + loggerInstance.info(o, s); } public static void warn(Object o, String s) { - myLogger.warn(o, s); + loggerInstance.warn(o, s); } public static void error(Object o, String s) { - myLogger.error(o, s); + loggerInstance.error(o, s); } public static void fatal(Object o, String s) { - myLogger.fatal(o, s); + loggerInstance.fatal(o, s); + } + + public static void reload() throws LoggerExc, LoggerFailure { + loggerInstance.reload(); } } diff --git a/source/mir/log/TestFramework.java b/source/mir/log/LoggerExc.java similarity index 80% rename from source/mir/log/TestFramework.java rename to source/mir/log/LoggerExc.java index 48a7891d..10bfd70b 100755 --- a/source/mir/log/TestFramework.java +++ b/source/mir/log/LoggerExc.java @@ -18,26 +18,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ - package mir.log; +import multex.Exc; -public class TestFramework { - - public static void main(String[] args) { - TestFramework t = new TestFramework(); - - Log.info( TestFramework.class, "class"); - Log.info( t, "object" ); - Log.info( null, "lalala" ); +public class LoggerExc extends Exc { + public LoggerExc(String aMessage) { + super(aMessage); } } diff --git a/source/mir/log/LoggerFailure.java b/source/mir/log/LoggerFailure.java new file mode 100755 index 00000000..f8d1b16c --- /dev/null +++ b/source/mir/log/LoggerFailure.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.log; + +import multex.Failure; + +public class LoggerFailure extends Failure { + + public LoggerFailure(String aMessage,Throwable aCause) { + super(aMessage, aCause); + } + + public LoggerFailure(Throwable aCause) { + this (aCause.getMessage(), aCause); + } +} diff --git a/source/mir/log/LoggerWrapper.java b/source/mir/log/LoggerWrapper.java index 7853ef98..eb8db650 100755 --- a/source/mir/log/LoggerWrapper.java +++ b/source/mir/log/LoggerWrapper.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ @@ -45,23 +45,23 @@ public class LoggerWrapper { } public void debug( String aMessage ) { - Log.debug(object, aMessage); + LoggerEngine.debug(object, aMessage); }; public void info( String aMessage ) { - Log.info(object, aMessage); + LoggerEngine.info(object, aMessage); }; public void warn( String aMessage ) { - Log.warn(object, aMessage); + LoggerEngine.warn(object, aMessage); }; public void error( String aMessage ) { - Log.error(object, aMessage); + LoggerEngine.error(object, aMessage); }; public void fatal( String aMessage ) { - Log.fatal(object, aMessage); + LoggerEngine.fatal(object, aMessage); }; public void message( int aType, String aMessage) { diff --git a/source/mir/log/log4j/LoggerImpl.java b/source/mir/log/log4j/LoggerImpl.java index 99ebed48..cd80fd83 100755 --- a/source/mir/log/log4j/LoggerImpl.java +++ b/source/mir/log/log4j/LoggerImpl.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.log.log4j; @@ -33,8 +33,8 @@ import java.util.HashMap; import java.util.Map; import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; - +import mir.log.LoggerExc; +import mir.log.LoggerFailure; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; @@ -42,33 +42,53 @@ import org.apache.log4j.PropertyConfigurator; public class LoggerImpl implements mir.log.Logger { private static Map loggers = new HashMap(); - public LoggerImpl() throws PropertiesConfigExc { - System.setProperty("log.home", - MirPropertiesConfiguration.instance().getStringWithHome("Log.Home")); - PropertyConfigurator.configure( - MirPropertiesConfiguration.instance().getStringWithHome("Log.log4j.ConfigurationFile").trim()); + public LoggerImpl() throws LoggerExc { + reload(); } + /** {@inheritDoc} */ public void debug(Object o, String s) { this.getLogger(o).debug(s); } + /** {@inheritDoc} */ public void info(Object o, String s) { this.getLogger(o).info(s); } + /** {@inheritDoc} */ public void warn(Object o, String s) { this.getLogger(o).warn(s); } + /** {@inheritDoc} */ public void error(Object o, String s) { this.getLogger(o).error(s); } + /** {@inheritDoc} */ public void fatal(Object o, String s) { this.getLogger(o).fatal(s); } + /** {@inheritDoc} */ + public void reload() throws LoggerExc, LoggerFailure { + try { + synchronized (loggers) { + System.setProperty("log.home", + MirPropertiesConfiguration.instance().getFile("Log.Home").getAbsolutePath()); + + PropertyConfigurator.configure( + MirPropertiesConfiguration.instance().getFile("Log.log4j.ConfigurationFile").getAbsolutePath()); + + loggers.clear(); + } + } + catch (Throwable t) { + throw new LoggerFailure(t); + } + } + private Logger getLogger(Object o) { String name; Logger l; diff --git a/source/mir/media/MediaHandler.java b/source/mir/media/MediaHandler.java index 33a45f41..a77ab2e2 100755 --- a/source/mir/media/MediaHandler.java +++ b/source/mir/media/MediaHandler.java @@ -30,9 +30,11 @@ package mir.media; import java.io.InputStream; +import java.io.File; import java.util.List; import mir.entity.Entity; +import mir.session.UploadedFile; /** * Interface for Media handling in Mir. All media handlers @@ -79,90 +81,65 @@ import mir.entity.Entity; * ) and just override the things that need to be specific. see MediaHandlerAudio * * @author , the Mir-coders group - * @version $Id: MediaHandler.java,v 1.1.2.2 2003/12/21 13:32:03 zapata Exp $ + * @version $Id: MediaHandler.java,v 1.1.2.3 2004/11/21 22:07:13 zapata Exp $ */ public interface MediaHandler { /** - * Takes the uploaded media data itself, along with the media Entity - * which contains the Media metadata plus the MediaType entity containing - * all the info for the specific media type itself. It's job is store the - * Media data (content) itself, this could be on the local filesystem, in the - * DB or even on a remote host. It then inserts the MetaData in the DB. - * @param InputStream, a stream of the uploaded data. - * @param ent, an Entity holding the media MetaData - * @param mediaType, an Entity holding the media_table entry - * @return boolean, success/fail - * @see mir.entity.Entity + * Store the media content from an {@link UploadedFile} */ - public void store(InputStream in, Entity ent, Entity mediaTypeEnt ) throws MediaExc, MediaFailure; + public void store(UploadedFile anUploadedFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure; + + /** + * Store the media content from an input stream. + */ + public void store(InputStream anInputStream, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure; + + /** + * Store the media content from a file. + */ + public void store(File aFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure; + + /** + * Perform production related tasks for this media. + */ + public void produce(Entity aMedia, Entity aMediaType ) throws MediaExc, MediaFailure; - public void produce(Entity ent, Entity mediaTypeEnt ) throws MediaExc, MediaFailure; /** * Get's the media data from storage and returns it as an InputStream * Not very useful for most media types as they are stored in a file, * but very usefull for ones stored in the DB as it is necessary to get * it first before making a file out of it (in Producer*). - * @param ent, an Entity holding the media MetaData - * @param mediaType, an Entity holding the media_table entry - * @return java.io.InputStream - * @see mir.entity.Entity */ - public InputStream getMedia (Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure; + public InputStream getMedia (Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure; /** * Pretty much like get() above. But get's the specific Icon * representation. useful for media stored in the DB. - * @param ent, an Entity holding the media MetaData - * @return java.io.InputStream - * @see mir.entity.Entity */ - public InputStream getThumbnail(Entity ent) throws MediaExc, MediaFailure; + public InputStream getThumbnail(Entity aMedia) throws MediaExc, MediaFailure; /** - * - * @param ent - * @return - * @throws MediaExc - * @throws MediaFailure + * Returns the mime-type of the media's thumbnail */ public String getThumbnailMimeType(Entity aMediaEntity, Entity aMediaType) throws MediaExc, MediaFailure; /** - * gets the final content representation for the media - * in the form of a URL (String) that allows someone to - * download, look at or listen to the media. (HREF, img src - * streaming link, etc..) - * It should use the helper functions in the StringUtil class to - * build URL's safely, eliminating any *illegal* user input. - * @param ent, an Entity holding the media MetaData - * @param mediaTypeEnt, an Entity holding the media_table entry - * @return String, the url. - * @see mir.entity.Entity - * @see mir.misc.StringUtil - */ - public List getURL (Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure; - - /** * Returns the absolute filesystem path to where the media * content should be stored. This path is usually defined * in the configuration wich is accessible through the MirConfig * class. - * @return String, the path. - * @see mir.misc.MirConfig */ public String getStoragePath () throws MediaExc, MediaFailure; - /** + /** * Returns the *relative* filesystem path to where the media * icon content should be stored. It is relative to the path * returned by getStoragePath() * This path is usually defined * in the configuration wich is accessible through the MirConfig * class. - * @return String, the path. - * @see mir.misc.MirConfig */ public String getIconStoragePath () throws MediaExc, MediaFailure; @@ -174,8 +151,6 @@ public interface MediaHandler { * It is usually defined * in the configuration witch is accessible through the MirConfig * class. - * @return String, the base URL to the host. - * @see mir.misc.MirConfig */ public String getPublishHost () throws MediaExc, MediaFailure; @@ -185,8 +160,6 @@ public interface MediaHandler { * It is usually defined * in the configuration wich is accessible through the MirConfig * class. - * @return String, the icon filename. - * @see mir.misc.MirConfig */ public String getBigIconName (); @@ -197,8 +170,6 @@ public interface MediaHandler { * It is usually defined * in the configuration wich is accessible through the MirConfig * class. - * @return String, the icon filename. - * @see mir.misc.MirConfig */ public String getTinyIconName (); @@ -214,7 +185,7 @@ public interface MediaHandler { * media type is. * @return String */ - public String getDescr (Entity mediaTypeEnt); + public String getDescr (Entity aMediaType); } diff --git a/source/mir/misc/FileUtil.java b/source/mir/misc/FileUtil.java index 63299e41..688d9514 100755 --- a/source/mir/misc/FileUtil.java +++ b/source/mir/misc/FileUtil.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.misc; @@ -39,28 +39,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Reader; - -import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; - /** * Hilfsklasse zum Mergen von Template und Daten */ public final class FileUtil { - - private static String producerStorageRoot; - - - static { - try { - producerStorageRoot = - MirPropertiesConfiguration.instance().getString("Producer.StorageRoot"); - } - catch (PropertiesConfigExc e) { - e.printStackTrace(); - } - } - /** * Privater Construktor to avoid accidental instantiation */ diff --git a/source/mir/module/AbstractModule.java b/source/mir/module/AbstractModule.java index 173f6ade..aea424ba 100755 --- a/source/mir/module/AbstractModule.java +++ b/source/mir/module/AbstractModule.java @@ -52,13 +52,12 @@ import mir.storage.StorageObject; public class AbstractModule { protected StorageObject storage; - public void setStorage(StorageObject storage) { - this.storage = storage; + public AbstractModule(StorageObject aStorageObject) { + storage = aStorageObject; } /** - * Liefert das Standard-StorageObject zur?ck, mit dem das Module assoziiert ist. - * @return Standard-StorageObject + * Returns the storage object associated with this module */ public StorageObject getStorageObject () { return storage; diff --git a/source/mir/producer/ResourceBundleProducerNode.java b/source/mir/producer/BundleProducerNode.java similarity index 60% rename from source/mir/producer/ResourceBundleProducerNode.java rename to source/mir/producer/BundleProducerNode.java index 26d11181..f7f8cdb8 100755 --- a/source/mir/producer/ResourceBundleProducerNode.java +++ b/source/mir/producer/BundleProducerNode.java @@ -18,61 +18,65 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; -import java.util.Locale; import java.util.Map; +import mir.bundle.Bundle; import mir.log.LoggerWrapper; import mir.util.ParameterExpander; -import mir.util.ResourceBundleGeneratorFunction; +import mir.util.generator.BundleGeneratorFunction; +import mircoders.global.MirGlobal; -import org.apache.struts.util.MessageResources; - -public class ResourceBundleProducerNode implements ProducerNode { +/** + * This producer node loads a bundle + */ +public class BundleProducerNode implements ProducerNode { private String key; private String bundleExpression; private String languageExpression; - public ResourceBundleProducerNode(String aKey, String aBundleExpression) { + public BundleProducerNode(String aKey, String aBundleExpression) { this (aKey, aBundleExpression, null); } - public ResourceBundleProducerNode(String aKey, String aBundleExpression, String aLanguageExpression) { + public BundleProducerNode(String aKey, String aBundleExpression, String aLanguageExpression) { bundleExpression = aBundleExpression; languageExpression = aLanguageExpression; key = aKey; } + /** {@inheritDoc} */ public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { - Object messages; - try { - if (languageExpression!=null) { - messages = - new ResourceBundleGeneratorFunction( - new Locale(ParameterExpander.expandExpression( aValueMap, languageExpression ), "" ), - MessageResources.getMessageResources( ParameterExpander.expandExpression( aValueMap, bundleExpression )) - ); - } - else { - messages = - MessageResources.getMessageResources( - ParameterExpander.expandExpression( aValueMap, bundleExpression )); + String bundle = ParameterExpander.expandExpression( aValueMap, bundleExpression ); + String[] languages = new String[0]; + if (languageExpression!=null) + languages = new String[] { ParameterExpander.expandExpression( aValueMap, languageExpression ) }; + + if (MirGlobal.config().getString("Producer.BundleCompatibility", "0").equals("1") && + bundle.startsWith("bundles.")) { + bundle = "etc/bundles/" + bundle.substring("bundles.".length()); } - ParameterExpander.setValueForKey( aValueMap, key, messages ); + + ParameterExpander.setValueForKey( + aValueMap, key, new BundleGeneratorFunction( + new Bundle[] { MirGlobal.getBundleFactory().getBundle( bundle, languages ) } + ) + ); } catch (Throwable t) { - aLogger.error("Failed to load bundle " + bundleExpression + " for language " + languageExpression + " into key " + key + ": " + t.getMessage()); + aLogger.error("Failed to load bundle " + bundleExpression + " for language " + + languageExpression + " into key " + key + ": " + t.getMessage()); } }; diff --git a/source/mir/producer/CompositeProducerNode.java b/source/mir/producer/CompositeProducerNode.java index 9f4db9e2..63fe79e4 100755 --- a/source/mir/producer/CompositeProducerNode.java +++ b/source/mir/producer/CompositeProducerNode.java @@ -18,21 +18,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Vector; import mir.log.LoggerWrapper; @@ -40,7 +40,7 @@ public class CompositeProducerNode implements ProducerNode { private List subNodes; public CompositeProducerNode() { - subNodes = new Vector(); + subNodes = new ArrayList(); } public CompositeProducerNode(ProducerNode[] aSubNodes) { diff --git a/source/mir/producer/DirCopyingProducerNode.java b/source/mir/producer/DirCopyingProducerNode.java index d4e823c4..2eb3b084 100755 --- a/source/mir/producer/DirCopyingProducerNode.java +++ b/source/mir/producer/DirCopyingProducerNode.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; @@ -39,10 +39,10 @@ import mir.util.ParameterExpander; public class DirCopyingProducerNode implements ProducerNode { private String sourceExpression; private String destinationExpression; - private String sourceBasePath; - private String destinationBasePath; + private File sourceBasePath; + private File destinationBasePath; - public DirCopyingProducerNode(String aSourceBasePath, String aDestinationBasePath, String aSource, String aDestination) { + public DirCopyingProducerNode(File aSourceBasePath, File aDestinationBasePath, String aSource, String aDestination) { sourceBasePath = aSourceBasePath; destinationBasePath = aDestinationBasePath; sourceExpression = aSource; @@ -52,8 +52,6 @@ public class DirCopyingProducerNode implements ProducerNode { public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { String source = ""; String destination = ""; - File sourceFile; - File destinationFile; try { source = ParameterExpander.expandExpression( aValueMap, sourceExpression ); diff --git a/source/mir/producer/EntityBatchingProducerNode.java b/source/mir/producer/EntityBatchingProducerNode.java index 50207c7a..aa0bf413 100755 --- a/source/mir/producer/EntityBatchingProducerNode.java +++ b/source/mir/producer/EntityBatchingProducerNode.java @@ -33,12 +33,13 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Vector; +import java.util.ArrayList; import mir.entity.adapter.EntityAdapterModel; import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; import mir.util.ParameterExpander; +import mir.util.StringRoutines; /** *

Title: EntityBatchingProducerNode

@@ -60,7 +61,7 @@ public class EntityBatchingProducerNode implements ProducerNode { private String batchDataKey; private EntityAdapterModel model; private String mainTablePrefix; - private List extraTables; + private String extraTables; private String definition; private String whereClause; private String orderByClause; @@ -76,7 +77,7 @@ public class EntityBatchingProducerNode implements ProducerNode { String aBatchInfoKey, EntityAdapterModel aModel, String aMainTablePrefix, - List someExtraTables, + String someExtraTables, String aDefinition, String aWhereClause, String anOrderByClause, @@ -103,7 +104,7 @@ public class EntityBatchingProducerNode implements ProducerNode { minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression; nrBatchesToProcessExpression = aNrBatchesToProcessExpression; } - + protected boolean isAborted(Map aValueMap) { Object producerValue = aValueMap.get(NodedProducer.PRODUCER_KEY); return ( @@ -112,14 +113,12 @@ public class EntityBatchingProducerNode implements ProducerNode { } public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { - Iterator browser; int nrEntities; int nrBatchesAfterFirst; int nrEntitiesInFirstBatch; int nrBatchesToProcess; List batchesData; int i; - int position; Map batchData; String expandedWhereClause; String expandedOrderByClause; @@ -140,11 +139,13 @@ public class EntityBatchingProducerNode implements ProducerNode { nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression); nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression); minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression); + List extraTableList = StringRoutines.splitString(ParameterExpander.expandExpression( aValueMap, extraTables).trim(), ","); - batchesData = new Vector(); - batchLocations = new Vector(); + batchesData = new ArrayList(); + batchLocations = new ArrayList(); - nrEntities = model.getMappingForName(definition).getStorage().getSize(mainTablePrefix, extraTables, expandedWhereClause)-nrEntitiesToSkip; + nrEntities = model.getMappingForName(definition).getStorage().getSize( + mainTablePrefix, extraTableList, expandedWhereClause)-nrEntitiesToSkip; nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch; while (nrEntitiesInFirstBatch=nrEntitiesPerBatch) nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch; @@ -196,9 +197,9 @@ public class EntityBatchingProducerNode implements ProducerNode { else batchData.put("next", null); - Iterator j = new EntityIteratorAdapter(mainTablePrefix, extraTables, expandedWhereClause, expandedOrderByClause, + Iterator j = new EntityIteratorAdapter(mainTablePrefix, extraTableList, expandedWhereClause, expandedOrderByClause, location.nrEntities, model, definition, location.nrEntities, location.firstEntity); - List entities = new Vector(); + List entities = new ArrayList(); while (j.hasNext()) entities.add(0, j.next()); diff --git a/source/mir/producer/EntityEnumeratingProducerNode.java b/source/mir/producer/EntityEnumeratingProducerNode.java index da7bd9ea..ca4fef8e 100755 --- a/source/mir/producer/EntityEnumeratingProducerNode.java +++ b/source/mir/producer/EntityEnumeratingProducerNode.java @@ -18,32 +18,32 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; import java.util.Iterator; -import java.util.List; import java.util.Map; import mir.entity.adapter.EntityAdapterModel; import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; import mir.util.ParameterExpander; +import mir.util.StringRoutines; public class EntityEnumeratingProducerNode extends ProducerNodeDecorator { private String key; private EntityAdapterModel model; private String definition; private String mainTablePrefix; - private List extraTables; + private String extraTables; private String skip; private String limit; private String whereClause; @@ -52,7 +52,7 @@ public class EntityEnumeratingProducerNode extends ProducerNodeDecorator { public EntityEnumeratingProducerNode( String aKey, EntityAdapterModel aModel, String aMainTablePrefix, - List someExtraTables, String aDefinition, + String anExtraTables, String aDefinition, String aWhereClause, String anOrderByClause, String aLimit, String aSkip, ProducerNode aSubNode) { @@ -62,7 +62,7 @@ public class EntityEnumeratingProducerNode extends ProducerNodeDecorator { definition = aDefinition; key = aKey; mainTablePrefix=aMainTablePrefix; - extraTables=someExtraTables; + extraTables = anExtraTables; whereClause = aWhereClause; orderByClause = anOrderByClause; @@ -76,7 +76,7 @@ public class EntityEnumeratingProducerNode extends ProducerNodeDecorator { try { browser = new EntityIteratorAdapter( mainTablePrefix, - extraTables, + StringRoutines.splitString(ParameterExpander.expandExpression( aValueMap, extraTables).trim(), ","), ParameterExpander.expandExpression( aValueMap, whereClause ), ParameterExpander.expandExpression( aValueMap, orderByClause ), 100, diff --git a/source/mir/producer/EntityListProducerNode.java b/source/mir/producer/EntityListProducerNode.java index 9b151d1a..32e0d3a8 100755 --- a/source/mir/producer/EntityListProducerNode.java +++ b/source/mir/producer/EntityListProducerNode.java @@ -18,65 +18,55 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; -import java.util.List; +import java.util.Collections; import java.util.Map; -import java.util.Vector; import mir.entity.adapter.EntityAdapterModel; import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; import mir.util.CachingRewindableIterator; import mir.util.ParameterExpander; +import mir.util.StringRoutines; public class EntityListProducerNode extends ProducerNodeDecorator { - private String key; + private String keyExpression; private String whereClause; private String orderByClause; private String mainTablePrefix; - private List extraTables; - private int batchSize; + private String extraTables; private EntityAdapterModel model; private String definition; private String limitExpression; private String skipExpression; public EntityListProducerNode(String aKey, - EntityAdapterModel aModel, String aMainTablePrefix, List someExtraTables, + EntityAdapterModel aModel, String aMainTablePrefix, String anExtraTables, String aDefinition, String aWhereClause, String anOrderByClause, String aLimitExpression, String aSkipExpression, ProducerNode aSubNode) { super(aSubNode); model = aModel; mainTablePrefix = aMainTablePrefix; - extraTables = someExtraTables; + extraTables = anExtraTables; definition = aDefinition; - key = aKey; + keyExpression = aKey; whereClause = aWhereClause; orderByClause = anOrderByClause; limitExpression = aLimitExpression; skipExpression = aSkipExpression; } - public EntityListProducerNode(String aKey, - EntityAdapterModel aModel, String aMainTablePrefix, List someExtraTables, - String aDefinition, String aWhereClause, String anOrderByClause, - int aLimit, int aSkip, ProducerNode aSubNode) { - this(aKey, aModel, aMainTablePrefix, someExtraTables, - aDefinition, aWhereClause, anOrderByClause, - Integer.toString(aLimit), Integer.toString(aSkip), aSubNode); - } - public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure, ProducerExc { try { int limit = ParameterExpander.evaluateIntegerExpressionWithDefault(aValueMap, limitExpression, -1); @@ -84,36 +74,42 @@ public class EntityListProducerNode extends ProducerNodeDecorator { if (skipExpression != null && !skipExpression.trim().equals("")) skip = ParameterExpander.evaluateIntegerExpression(aValueMap, skipExpression); + String key = ParameterExpander.expandExpression(aValueMap, keyExpression); - ParameterExpander.setValueForKey( - aValueMap, - key, - new CachingRewindableIterator( - new EntityIteratorAdapter( mainTablePrefix, extraTables, - ParameterExpander.expandExpression( aValueMap, whereClause ), - ParameterExpander.expandExpression( aValueMap, orderByClause ), - Math.min(50, limit), - model, - definition, - limit, - skip ) - ) - ); - } - catch (Throwable t) { - aLogger.error("cannot retrieve list into key " + key + ": " + t.getMessage()); try { ParameterExpander.setValueForKey( aValueMap, key, - new CachingRewindableIterator(new Vector().iterator()) + new CachingRewindableIterator( + new EntityIteratorAdapter( mainTablePrefix, + StringRoutines.splitString(ParameterExpander.expandExpression( aValueMap, extraTables).trim(), ","), + ParameterExpander.expandExpression( aValueMap, whereClause ), + ParameterExpander.expandExpression( aValueMap, orderByClause ), + Math.min(50, limit), + model, + definition, + limit, + skip ) + ) ); } - catch (Throwable s) { + catch (Throwable t) { + aLogger.error("cannot retrieve list into keyExpression " + key + ": " + t.getMessage()); + try { + ParameterExpander.setValueForKey( + aValueMap, + key, + new CachingRewindableIterator(Collections.EMPTY_LIST.iterator()) + ); + } + catch (Throwable s) { + } } } + catch (Throwable t) { + aLogger.error("cannot process entity list producer node: : " + t.getMessage()); + } super.produce(aValueMap, aVerb, aLogger); - }; - + } } \ No newline at end of file diff --git a/source/mir/producer/ScriptCallingProducerNode.java b/source/mir/producer/ExecuteProgramProducerNode.java similarity index 67% rename from source/mir/producer/ScriptCallingProducerNode.java rename to source/mir/producer/ExecuteProgramProducerNode.java index 75c51918..0c57a150 100755 --- a/source/mir/producer/ScriptCallingProducerNode.java +++ b/source/mir/producer/ExecuteProgramProducerNode.java @@ -34,27 +34,31 @@ import java.util.Map; import mir.log.LoggerWrapper; import mir.util.ParameterExpander; -public class ScriptCallingProducerNode implements ProducerNode { +public class ExecuteProgramProducerNode implements ProducerNode { private String scriptExpression; private String maxDurationExpression; + private String outputVariableExpression; + private String returnValueVariableExpression; - public ScriptCallingProducerNode(String aScriptExpression, String aMaxDurationExpression) { + public ExecuteProgramProducerNode(String aScriptExpression, String aMaxDurationExpression, String anOutputVariableExpression, + String aReturnValueVariableExpression) { scriptExpression = aScriptExpression; maxDurationExpression = aMaxDurationExpression; + outputVariableExpression = anOutputVariableExpression; + returnValueVariableExpression = aReturnValueVariableExpression; } public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { String script; long maxDuration; - Process process; - int returnValue; try { script = ParameterExpander.expandExpression(aValueMap, scriptExpression); maxDuration = ParameterExpander.evaluateIntegerExpressionWithDefault(aValueMap, maxDurationExpression, 0); - ProcessRunner runner = new ProcessRunner(Runtime.getRuntime().exec(script)); + ProcessRunner runner = new ProcessRunner(aLogger, script); runner.start(); + synchronized (runner) { runner.wait(maxDuration); } @@ -62,23 +66,32 @@ public class ScriptCallingProducerNode implements ProducerNode { if (runner.getFinished()) { aLogger.info(script + " terminated successfully, return value = " + runner.getReturnValue() + "."); + + if (returnValueVariableExpression != null) { + ParameterExpander.setValueForKey(aValueMap, + ParameterExpander.expandExpression(aValueMap, returnValueVariableExpression), + new Integer(runner.getReturnValue())); + } + } else { aLogger.info(script + " interrupted prematurely after " + maxDuration + "ms."); } } catch (Throwable e) { - aLogger.error(scriptExpression + " failed to execute: " + e.getMessage()); + aLogger.error("Error while executing " + scriptExpression + " : " + e.toString()); } } private static class ProcessRunner extends Thread { - private Process process; + private String script; private boolean finished = false; private int returnValue = 0; + private LoggerWrapper logger; - public ProcessRunner(Process aProcess) { - process = aProcess; + public ProcessRunner(LoggerWrapper aLogger, String aScript) { + script = aScript; + logger = aLogger; } public boolean getFinished() { @@ -90,15 +103,24 @@ public class ScriptCallingProducerNode implements ProducerNode { } public void run() { + Process process = null; try { + process = Runtime.getRuntime().exec(script); returnValue = process.waitFor(); + finished = true; + synchronized (this) { this.notify(); } } catch (InterruptedException e) { - process.destroy(); + if (process!=null) { + process.destroy(); + } + } + catch (Exception e) { + logger.error(script + " failed to execute: " + e.getMessage()); } } } diff --git a/source/mir/producer/ExternalDbProducerNode.java b/source/mir/producer/ExternalDbProducerNode.java new file mode 100755 index 00000000..cfc1e51c --- /dev/null +++ b/source/mir/producer/ExternalDbProducerNode.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.producer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.sql.*; + + +import mir.log.LoggerWrapper; +import mir.util.ExceptionFunctions; +import mir.util.ParameterExpander; + +public class ExternalDbProducerNode extends ProducerNodeDecorator { + private String key; + private String driver; + private String host; + private String port; + private String database; + private String username; + private String password; + private String query; + + + public ExternalDbProducerNode(String aKey, String aDriver, String aHost, String aPort, String aDatabase, String aUsername, String aPassword,String aQuery,ProducerNode aSubNode) { + super(aSubNode); + key = aKey; + driver = aDriver; + host = aHost; + port = aPort; + database = aDatabase; + username = aUsername; + password = aPassword; + query =aQuery; + + } + + public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { + try { + String expandedKey = ParameterExpander.expandExpression( aValueMap, key ); + String expandedDriver = ParameterExpander.expandExpression( aValueMap, driver); + String expandedHost = ParameterExpander.expandExpression( aValueMap, host); + String expandedPort = ParameterExpander.expandExpression( aValueMap, port); + String expandedDatabase = ParameterExpander.expandExpression( aValueMap, database); + String expandedUsername = ParameterExpander.expandExpression( aValueMap, username); + String expandedPassword = ParameterExpander.expandExpression( aValueMap, password); + String expandedQuery = ParameterExpander.expandExpression( aValueMap, query); + + if (expandedDriver.equals("postgresql")){ + Class.forName("org.postgresql.Driver"); + } + if (expandedDriver.equals("mysql")){ + Class.forName("com.mysql.jdbc.Driver"); + } + else { + throw new Exception("Unsupported DB Driver:"+expandedDriver); + } + + Connection db = DriverManager.getConnection("jdbc:"+expandedDriver+"://"+expandedHost + +":"+expandedPort+"/"+expandedDatabase + , expandedUsername, expandedPassword); + + Statement st = db.createStatement(); + ResultSet rs = st.executeQuery(expandedQuery); + ResultSetMetaData rsmd = rs.getMetaData(); + int numberOfColumns= rsmd.getColumnCount(); + ArrayList fieldNames = new ArrayList(numberOfColumns); + for (int i=0;itrue if aVerb is a valid verb for this factory + */ public boolean allowVerb(String aVerb); + /** + * Instantiates a producer based on the supplied verb + */ public Producer makeProducer(String aVerb, Map aStartingValues) throws ProducerFailure, ProducerExc; - public Iterator verbs(); /* returns ProducerVerbs */ + + /** + * The set of pre-defined verbs. Returns a list of {@link ProducerVerb}s + */ + public List verbs(); } diff --git a/source/mir/producer/ProducerNode.java b/source/mir/producer/ProducerNode.java index 084e58ee..2e0f7c8f 100755 --- a/source/mir/producer/ProducerNode.java +++ b/source/mir/producer/ProducerNode.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.producer; @@ -33,6 +33,14 @@ import java.util.Map; import mir.log.LoggerWrapper; +/** + * A ProducerNode is an atom of a noded producer factory. + * + */ public interface ProducerNode { + /** + * Perform the operations of the producer node, based on a verb and a value set. + * The supplied logger object should be used for any logging. + */ public void produce(Map aValueSet, String aVerb, LoggerWrapper aLogger) throws ProducerExc, ProducerFailure; } \ No newline at end of file diff --git a/source/mir/producer/RSSProducerNode.java b/source/mir/producer/RSSProducerNode.java index d61c96ef..9d62022a 100755 --- a/source/mir/producer/RSSProducerNode.java +++ b/source/mir/producer/RSSProducerNode.java @@ -42,11 +42,17 @@ public class RSSProducerNode implements ProducerNode { private String key; private String url; private String version; + private String encoding; - public RSSProducerNode(String aKey, String anURL, String aVersion) { + public RSSProducerNode(String aKey, String aURL, String aVersion) { + this (aKey, aURL, aVersion, null); + } + + public RSSProducerNode(String aKey, String aURL, String aVersion, String anEncoding) { key = aKey; - url = anURL; + url = aURL; version = aVersion; + encoding = anEncoding; } public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { @@ -55,16 +61,30 @@ public class RSSProducerNode implements ProducerNode { String expandedKey = ParameterExpander.expandExpression( aValueMap, key ); String expandedUrl = ParameterExpander.expandExpression( aValueMap, url ); String expandedVersion = ParameterExpander.expandExpression( aValueMap, version ); + String expandedEncoding = null; + if (encoding!=null) { + expandedEncoding = ParameterExpander.expandExpression( aValueMap, encoding ); + } ParameterExpander.setValueForKey(aValueMap, expandedKey, null); - if (version.equals("1.0")) { + if (expandedVersion.equals("1.0")) { RSSReader reader = new RSSReader(); - rssData = reader.parseUrl(expandedUrl); + if (expandedEncoding!=null) { + rssData = reader.parseUrl(expandedUrl, expandedEncoding); + } + else { + rssData = reader.parseUrl(expandedUrl); + } } - else if (version.equals("0.91")) { + else if (expandedVersion.equals("0.91")) { RSS091Reader reader = new RSS091Reader(); - rssData = reader.parseUrl(expandedUrl); + if (expandedEncoding!=null) { + rssData = reader.parseUrl(expandedUrl, expandedEncoding); + } + else { + rssData = reader.parseUrl(expandedUrl); + } } ParameterExpander.setValueForKey(aValueMap, expandedKey, rssData); } diff --git a/source/mir/producer/reader/DefaultProducerNodeBuilders.java b/source/mir/producer/reader/DefaultProducerNodeBuilders.java index b3024f19..c2f9a018 100755 --- a/source/mir/producer/reader/DefaultProducerNodeBuilders.java +++ b/source/mir/producer/reader/DefaultProducerNodeBuilders.java @@ -36,6 +36,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.io.File; import mir.entity.adapter.EntityAdapterModel; import mir.generator.Generator; @@ -50,6 +51,7 @@ import mir.producer.EntityListProducerNode; import mir.producer.EntityModifyingProducerNode; import mir.producer.EvaluatedAssignmentProducerNode; import mir.producer.ExpandedAssignmentProducerNode; +import mir.producer.ExternalDbProducerNode; import mir.producer.FileDateSettingProducerNode; import mir.producer.FileDeletingProducerNode; import mir.producer.FreeQueryProducerNode; @@ -60,24 +62,25 @@ import mir.producer.LoopProducerNode; import mir.producer.ProducerNode; import mir.producer.RDFAggregatorProducerNode; import mir.producer.RSSProducerNode; -import mir.producer.ResourceBundleProducerNode; -import mir.producer.ScriptCallingProducerNode; +import mir.producer.BundleProducerNode; +import mir.producer.ExecuteProgramProducerNode; import mir.util.StringRoutines; -import mir.util.xml.*; +import mir.util.xml.XMLParserExc; import mir.util.xml.XMLReaderTool; public class DefaultProducerNodeBuilders { public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary, - EntityAdapterModel aModel, Generator.GeneratorLibrary aGeneratorLibrary, - WriterEngine aWriterEngine, String aSourceBasePath, String aDestinationBasePath) throws ProducerConfigExc { + EntityAdapterModel aModel, Generator.Library aGeneratorLibrary, + WriterEngine aWriterEngine, File aSourceBasePath, File aDestinationBasePath) throws ProducerConfigExc { aBuilderLibrary.registerBuilder("Set", EvaluatedAssignmentProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("Define", ExpandedAssignmentProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("Log", LoggingProducerNodeBuilder.class); - aBuilderLibrary.registerBuilder("Execute", ScriptCallingProducerNodeBuilder.class); - aBuilderLibrary.registerBuilder("Resource", ResourceBundleProducerNodeBuilder.class); - aBuilderLibrary.registerFactory("CopyDir", new DirCopyProducerNodeBuilder.factory( aSourceBasePath, aDestinationBasePath)); + aBuilderLibrary.registerBuilder("Execute", ExecuteProgramProducerNodeBuilder.class); + aBuilderLibrary.registerBuilder("Resource", BundleProducerNodeBuilder.class); + aBuilderLibrary.registerBuilder("Bundle", BundleProducerNodeBuilder.class); + aBuilderLibrary.registerFactory("CopyDir", new DirCopyProducerNodeBuilder.factory(aSourceBasePath, aDestinationBasePath)); aBuilderLibrary.registerBuilder("DeleteFile", FileDeletingProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("SetFileDate", FileDateSettingProducerNodeBuilder.class); @@ -88,6 +91,7 @@ public class DefaultProducerNodeBuilders { aBuilderLibrary.registerBuilder("RDFAggregate", RDFAggregatorProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("FreeQuery", FreeQueryProducerNodeBuilder.class); + aBuilderLibrary.registerBuilder("ExternalDbQuery", ExternalDbProducerNodeBuilder.class); aBuilderLibrary.registerFactory("Enumerate", new EnumeratingProducerNodeBuilder.factory(aModel)); aBuilderLibrary.registerFactory("List", new ListProducerNodeBuilder.factory(aModel)); @@ -97,8 +101,7 @@ public class DefaultProducerNodeBuilders { aBuilderLibrary.registerFactory("CreateEntity", new CreateEntityProducerNodeBuilder.factory(aModel)); aBuilderLibrary.registerFactory("DeleteEntity", new DeleteEntityProducerNodeBuilder.factory(aModel)); - aBuilderLibrary.registerFactory("Generate", - new GeneratingProducerNodeBuilder.factory(aGeneratorLibrary, aWriterEngine)); + aBuilderLibrary.registerFactory("Generate", new GeneratingProducerNodeBuilder.factory(aGeneratorLibrary, aWriterEngine)); } public static abstract class AbstractProducerNodeBuilder implements ProducerNodeBuilder { @@ -128,6 +131,7 @@ public class DefaultProducerNodeBuilders { // general attribute names, specifc builders reference these, to keep attribute // names consistent + public final static String EXTRA_TABLES_ATTRIBUTE = "extratables"; public final static String SELECTION_ATTRIBUTE = "selection"; public final static String ORDER_ATTRIBUTE = "order"; public final static String DEFINITION_ATTRIBUTE = "table"; @@ -154,7 +158,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE); value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE); @@ -177,7 +181,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, ASSIGNMENT_REQUIRED_ATTRIBUTES, ASSIGNMENT_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(ASSIGNMENT_KEY_ATTRIBUTE); value = (String) anAttributes.get(ASSIGNMENT_VALUE_ATTRIBUTE); @@ -199,7 +203,7 @@ public class DefaultProducerNodeBuilders { private final static String ENUMERATION_DEFAULT_SUBNODE = "default"; private final static String ENUMERATION_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE; private final static String ENUMERATION_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE; - private final static String ENUMERATION_EXTRATABLES_ATTRIBUTE = "extratables"; + private final static String ENUMERATION_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE; private final static String[] ENUMERATION_LIST_REQUIRED_ATTRIBUTES = { ENUMERATION_LIST_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE }; private final static String[] ENUMERATION_LIST_OPTIONAL_ATTRIBUTES = { }; private final static String[] ENUMERATION_QUERY_REQUIRED_ATTRIBUTES = { ENUMERATION_DEFINITION_ATTRIBUTE, ENUMERATION_KEY_ATTRIBUTE }; @@ -209,7 +213,7 @@ public class DefaultProducerNodeBuilders { private String key; private String definition; private String mainTablePrefix; - private List extraTables; + private String extraTables; private String list; private String selection; private String order; @@ -232,17 +236,17 @@ public class DefaultProducerNodeBuilders { if (list!=null) - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_LIST_REQUIRED_ATTRIBUTES, ENUMERATION_LIST_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_LIST_REQUIRED_ATTRIBUTES, ENUMERATION_LIST_OPTIONAL_ATTRIBUTES); if (definition!=null) - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_QUERY_REQUIRED_ATTRIBUTES, ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, ENUMERATION_QUERY_REQUIRED_ATTRIBUTES, ENUMERATION_QUERY_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(ENUMERATION_KEY_ATTRIBUTE); - selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, ""); - order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, ""); + selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_SELECTION_ATTRIBUTE, ""); + order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_ORDER_ATTRIBUTE, ""); limit = (String) anAttributes.get(ENUMERATION_LIMIT_ATTRIBUTE); skip = (String) anAttributes.get(ENUMERATION_SKIP_ATTRIBUTE); - extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_EXTRATABLES_ATTRIBUTE,"").trim(), ","); + extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, ENUMERATION_EXTRATABLES_ATTRIBUTE,""); if (definition!=null) { List parts = StringRoutines.splitString(definition.trim(), " "); if (parts.size() > 0) @@ -390,10 +394,10 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, LOOP_REQUIRED_ATTRIBUTES, LOOP_OPTIONAL_ATTRIBUTES); condition = (String) anAttributes.get(LOOP_CONDITION_ATTRIBUTE); - limit = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, ""); + limit = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOOP_LIMIT_ATTRIBUTE, ""); }; public ProducerNode constructNode() { @@ -407,7 +411,7 @@ public class DefaultProducerNodeBuilders { private final static String LIST_KEY_ATTRIBUTE = KEY_ATTRIBUTE; private final static String LIST_DEFINITION_ATTRIBUTE = DEFINITION_ATTRIBUTE; private final static String LIST_SELECTION_ATTRIBUTE = SELECTION_ATTRIBUTE; - private final static String LIST_EXTRATABLES_ATTRIBUTE = "extratables"; + private final static String LIST_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE; private final static String LIST_ORDER_ATTRIBUTE = ORDER_ATTRIBUTE; private final static String LIST_LIMIT_ATTRIBUTE = LIMIT_ATTRIBUTE; private final static String LIST_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE; @@ -418,7 +422,7 @@ public class DefaultProducerNodeBuilders { private String key; private String definition; private String mainTablePrefix; - private List extraTables; + private String extraTables; private String selection; private String order; private String limit; @@ -432,15 +436,15 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, LIST_REQUIRED_ATTRIBUTES, LIST_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(LIST_KEY_ATTRIBUTE); definition = (String) anAttributes.get(LIST_DEFINITION_ATTRIBUTE); - selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, ""); - order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, ""); + selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_SELECTION_ATTRIBUTE, ""); + order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_ORDER_ATTRIBUTE, ""); limit = (String) anAttributes.get(LIST_LIMIT_ATTRIBUTE); skip = (String) anAttributes.get(LIST_SKIP_ATTRIBUTE); - extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_EXTRATABLES_ATTRIBUTE,"").trim(), ","); + extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LIST_EXTRATABLES_ATTRIBUTE,""); List parts = StringRoutines.splitString(definition.trim()," "); if (parts.size()>0) definition=(String)parts.get(0); if (parts.size()>1) mainTablePrefix=(String)parts.get(1); @@ -485,10 +489,10 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, DELETEENTITY_REQUIRED_ATTRIBUTES, DELETEENTITY_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, DELETEENTITY_REQUIRED_ATTRIBUTES, DELETEENTITY_OPTIONAL_ATTRIBUTES); definition = (String) anAttributes.get(DELETEENTITY_DEFINITION_ATTRIBUTE); - selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, DELETEENTITY_SELECTION_ATTRIBUTE, ""); + selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, DELETEENTITY_SELECTION_ATTRIBUTE, ""); }; public ProducerNode constructNode() { @@ -527,7 +531,7 @@ public class DefaultProducerNodeBuilders { public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { String typeString; - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, LOG_REQUIRED_ATTRIBUTES, LOG_OPTIONAL_ATTRIBUTES); message = (String) anAttributes.get(LOG_MESSAGE_ATTRIBUTE); if (anAttributes.containsKey(LOG_TYPE_ATTRIBUTE)) { @@ -578,7 +582,7 @@ public class DefaultProducerNodeBuilders { public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { String typeString; - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, FREEQUERY_REQUIRED_ATTRIBUTES, FREEQUERY_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, FREEQUERY_REQUIRED_ATTRIBUTES, FREEQUERY_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(FREEQUERY_KEY_ATTRIBUTE); query = (String) anAttributes.get(FREEQUERY_QUERY_ATTRIBUTE); @@ -606,10 +610,57 @@ public class DefaultProducerNodeBuilders { return new FreeQueryProducerNode(key, query, limit, type); }; } +//////////////////////////////////////////////////////////////////////////////// + + public static class ExternalDbProducerNodeBuilder extends AbstractProducerNodeBuilder { + private final static String EXTDB_KEY_ATTRIBUTE = KEY_ATTRIBUTE; + private final static String EXTDB_DRIVER_ATTRIBUTE = "driver"; + private final static String EXTDB_HOST_ATTRIBUTE = "host"; + private final static String EXTDB_PORT_ATTRIBUTE = "port"; + private final static String EXTDB_DATABASE_ATTRIBUTE = "database"; + private final static String EXTDB_USERNAME_ATTRIBUTE = "username"; + private final static String EXTDB_PASSWORD_ATTRIBUTE = "password"; + private final static String EXTDB_QUERY_ATTRIBUTE = "query"; + private final static String EXTDB_DEFAULT_SUBNODE = "default"; + private final static String[] EXTDB_REQUIRED_ATTRIBUTES = { KEY_ATTRIBUTE, EXTDB_DRIVER_ATTRIBUTE, EXTDB_HOST_ATTRIBUTE, EXTDB_PORT_ATTRIBUTE, EXTDB_DATABASE_ATTRIBUTE, EXTDB_USERNAME_ATTRIBUTE, EXTDB_PASSWORD_ATTRIBUTE, EXTDB_QUERY_ATTRIBUTE }; + private final static String[] EXTDB_OPTIONAL_ATTRIBUTES = { }; + private final static String[] EXTDB_SUBNODES = {EXTDB_DEFAULT_SUBNODE}; + + private String key; + private String driver; + private String host; + private String port; + private String database; + private String username; + private String password; + private String query; + + + public ExternalDbProducerNodeBuilder() { + super(EXTDB_SUBNODES); + } + + public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { + XMLReaderTool.checkAttributes(anAttributes, EXTDB_REQUIRED_ATTRIBUTES, EXTDB_OPTIONAL_ATTRIBUTES); + + key = (String) anAttributes.get(EXTDB_KEY_ATTRIBUTE); + driver = (String) anAttributes.get(EXTDB_DRIVER_ATTRIBUTE); + host = (String) anAttributes.get(EXTDB_HOST_ATTRIBUTE); + port = (String) anAttributes.get(EXTDB_PORT_ATTRIBUTE); + database = (String) anAttributes.get(EXTDB_DATABASE_ATTRIBUTE); + username = (String) anAttributes.get(EXTDB_USERNAME_ATTRIBUTE); + password = (String) anAttributes.get(EXTDB_PASSWORD_ATTRIBUTE); + query = (String) anAttributes.get(EXTDB_QUERY_ATTRIBUTE); + }; + + public ProducerNode constructNode() { + return new ExternalDbProducerNode(key, driver, host, port, database, username, password, query, getSubNode(EXTDB_DEFAULT_SUBNODE)); + }; + } //////////////////////////////////////////////////////////////////////////////// - public static class ResourceBundleProducerNodeBuilder extends AbstractProducerNodeBuilder { + public static class BundleProducerNodeBuilder extends AbstractProducerNodeBuilder { private final static String RESOURCEBUNDLE_KEY_ATTRIBUTE = KEY_ATTRIBUTE; private final static String RESOURCEBUNDLE_BUNDLE_ATTRIBUTE = "bundle"; private final static String RESOURCEBUNDLE_LANGUAGE_ATTRIBUTE = "language"; @@ -621,12 +672,12 @@ public class DefaultProducerNodeBuilders { private String bundle; private String language; - public ResourceBundleProducerNodeBuilder() { + public BundleProducerNodeBuilder() { super(RESOURCEBUNDLE_SUBNODES); } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, RESOURCEBUNDLE_REQUIRED_ATTRIBUTES, RESOURCEBUNDLE_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(RESOURCEBUNDLE_KEY_ATTRIBUTE); bundle = (String) anAttributes.get(RESOURCEBUNDLE_BUNDLE_ATTRIBUTE); @@ -634,7 +685,7 @@ public class DefaultProducerNodeBuilders { }; public ProducerNode constructNode() { - return new ResourceBundleProducerNode(key, bundle, language); + return new BundleProducerNode(key, bundle, language); }; } @@ -655,7 +706,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, FILEDATESETTING_REQUIRED_ATTRIBUTES, FILEDATESETTING_OPTIONAL_ATTRIBUTES); fileNameKey = (String) anAttributes.get(FILEDATESETTING_FILE_ATTRIBUTE); dateKey = (String) anAttributes.get(FILEDATESETTING_DATE_ATTRIBUTE); @@ -681,7 +732,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, FILEDELETING_REQUIRED_ATTRIBUTES, FILEDELETING_OPTIONAL_ATTRIBUTES); fileNameKey = (String) anAttributes.get(FILEDELETING_FILE_ATTRIBUTE); }; @@ -693,30 +744,36 @@ public class DefaultProducerNodeBuilders { //////////////////////////////////////////////////////////////////////////////// - public static class ScriptCallingProducerNodeBuilder extends AbstractProducerNodeBuilder { - private final static String SCRIPT_COMMAND_ATTRIBUTE = "command"; - private final static String SCRIPT_TIME_ATTRIBUTE = "time"; - private final static String[] SCRIPT_REQUIRED_ATTRIBUTES = { SCRIPT_COMMAND_ATTRIBUTE }; - private final static String[] SCRIPT_OPTIONAL_ATTRIBUTES = {}; - private final static String[] SCRIPT_SUBNODES = {}; + public static class ExecuteProgramProducerNodeBuilder extends AbstractProducerNodeBuilder { + private final static String EXECUTEPROGRAM_COMMAND_ATTRIBUTE = "command"; + private final static String EXECUTEPROGRAM_MAXTIME_ATTRIBUTE = "maxduration"; + private final static String EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE = "resultvar"; + private final static String EXECUTEPROGRAM_RETURNVALUE_ATTRIBUTE = "returnvaluevar"; + private final static String[] EXECUTEPROGRAM_REQUIRED_ATTRIBUTES = { EXECUTEPROGRAM_COMMAND_ATTRIBUTE }; + private final static String[] EXECUTEPROGRAM_OPTIONAL_ATTRIBUTES = { EXECUTEPROGRAM_MAXTIME_ATTRIBUTE, EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE }; + private final static String[] EXECUTEPROGRAM_SUBNODES = {}; private String command; private String time; + private String resultvar; + private String returnValueVar; - public ScriptCallingProducerNodeBuilder() { - super(SCRIPT_SUBNODES); + public ExecuteProgramProducerNodeBuilder() { + super(EXECUTEPROGRAM_SUBNODES); } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, SCRIPT_REQUIRED_ATTRIBUTES, SCRIPT_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, EXECUTEPROGRAM_REQUIRED_ATTRIBUTES, EXECUTEPROGRAM_OPTIONAL_ATTRIBUTES); - command = (String) anAttributes.get(SCRIPT_COMMAND_ATTRIBUTE); - time = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, SCRIPT_TIME_ATTRIBUTE, "0"); + command = (String) anAttributes.get(EXECUTEPROGRAM_COMMAND_ATTRIBUTE); + time = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_MAXTIME_ATTRIBUTE, null); + resultvar = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_RESULTVAR_ATTRIBUTE, null); + returnValueVar = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXECUTEPROGRAM_RETURNVALUE_ATTRIBUTE, null); }; public ProducerNode constructNode() { return new - ScriptCallingProducerNode(command, time); + ExecuteProgramProducerNode(command, time, resultvar, returnValueVar); }; } @@ -731,10 +788,10 @@ public class DefaultProducerNodeBuilders { public static class DirCopyProducerNodeBuilder extends AbstractProducerNodeBuilder { private String source; private String destination; - private String sourceBasePath; - private String destinationBasePath; + private File sourceBasePath; + private File destinationBasePath; - public DirCopyProducerNodeBuilder(String aSourceBasePath, String aDestinationBasePath) { + public DirCopyProducerNodeBuilder(File aSourceBasePath, File aDestinationBasePath) { super(DIRCOPY_SUBNODES); sourceBasePath = aSourceBasePath; @@ -742,7 +799,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, DIRCOPY_REQUIRED_ATTRIBUTES, DIRCOPY_OPTIONAL_ATTRIBUTES); source = (String) anAttributes.get(DIRCOPY_SOURCE_ATTRIBUTE); destination = (String) anAttributes.get(DIRCOPY_DESTINATION_ATTRIBUTE); @@ -753,10 +810,10 @@ public class DefaultProducerNodeBuilders { }; public static class factory implements ProducerNodeBuilderFactory { - private String sourceBasePath; - private String destinationBasePath; + private File sourceBasePath; + private File destinationBasePath; - public factory(String aSourceBasePath, String aDestinationBasePath) { + public factory(File aSourceBasePath, File aDestinationBasePath) { sourceBasePath = aSourceBasePath; destinationBasePath = aDestinationBasePath; } @@ -780,10 +837,10 @@ public class DefaultProducerNodeBuilders { private String generator; private String destination; private String parameters; - private Generator.GeneratorLibrary generatorLibrary; + private Generator.Library generatorLibrary; private WriterEngine writerEngine; - public GeneratingProducerNodeBuilder(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) { + public GeneratingProducerNodeBuilder(Generator.Library aGeneratorLibrary, WriterEngine aWriterEngine) { super(GENERATION_SUBNODES); writerEngine = aWriterEngine; @@ -791,11 +848,11 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, GENERATION_REQUIRED_ATTRIBUTES, GENERATION_OPTIONAL_ATTRIBUTES); generator = (String) anAttributes.get(GENERATION_GENERATOR_ATTRIBUTE); destination = (String) anAttributes.get(GENERATION_DESTINATION_ATTRIBUTE); - parameters = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" ); + parameters = XMLReaderTool.getStringAttributeWithDefault(anAttributes, GENERATION_PARAMETERS_ATTRIBUTE, "" ); }; public ProducerNode constructNode() { @@ -803,10 +860,10 @@ public class DefaultProducerNodeBuilders { }; public static class factory implements ProducerNodeBuilderFactory { - private Generator.GeneratorLibrary generatorLibrary; + private Generator.Library generatorLibrary; private WriterEngine writerEngine; - public factory(Generator.GeneratorLibrary aGeneratorLibrary, WriterEngine aWriterEngine) { + public factory(Generator.Library aGeneratorLibrary, WriterEngine aWriterEngine) { writerEngine = aWriterEngine; generatorLibrary = aGeneratorLibrary; } @@ -832,7 +889,7 @@ public class DefaultProducerNodeBuilders { private final static String BATCHER_SKIP_ATTRIBUTE = SKIP_ATTRIBUTE; private final static String BATCHER_PROCESS_ATTRIBUTE = "process"; - private final static String BATCHER_EXTRATABLES_ATTRIBUTE = "extratables"; + private final static String BATCHER_EXTRATABLES_ATTRIBUTE = EXTRA_TABLES_ATTRIBUTE; private final static String BATCHER_BATCH_SUBNODE = "batches"; private final static String BATCHER_BATCHLIST_SUBNODE = "batchlist"; @@ -844,7 +901,7 @@ public class DefaultProducerNodeBuilders { private String batchDataKey; private String batchInfoKey; private String mainTablePrefix; - private List extraTables; + private String extraTables; private String definition; private String selection; private String order; @@ -860,22 +917,24 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES); - - batchDataKey = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" ); - batchInfoKey = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" ); - definition = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" ); - selection = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" ); - order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" ); - - batchSize = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" ); - minBatchSize = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" ); - skip = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" ); - process = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" ); - extraTables = StringRoutines.splitString(mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_EXTRATABLES_ATTRIBUTE,"").trim(), ","); - List parts = StringRoutines.splitString(definition.trim()," "); - if (parts.size()>0) definition=(String)parts.get(0); - if (parts.size()>1) mainTablePrefix=(String)parts.get(1); + XMLReaderTool.checkAttributes(anAttributes, BATCHER_REQUIRED_ATTRIBUTES, BATCHER_OPTIONAL_ATTRIBUTES); + + batchDataKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DATAKEY_ATTRIBUTE, "data" ); + batchInfoKey = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_INFOKEY_ATTRIBUTE, "info" ); + definition = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_DEFINITION_ATTRIBUTE, "" ); + selection = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SELECTION_ATTRIBUTE, "" ); + order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_ORDER_ATTRIBUTE, "" ); + + batchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_BATCHSIZE_ATTRIBUTE, "20" ); + minBatchSize = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_MINBATCHSIZE_ATTRIBUTE, "0" ); + skip = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_SKIP_ATTRIBUTE, "0" ); + process = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_PROCESS_ATTRIBUTE, "-1" ); + + extraTables = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BATCHER_EXTRATABLES_ATTRIBUTE, ""); + + List parts = StringRoutines.splitString(definition.trim(), " "); + if (parts.size()>0) definition = (String) parts.get(0); + if (parts.size()>1) mainTablePrefix = (String) parts.get(1); }; public ProducerNode constructNode() { @@ -928,7 +987,7 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, IF_REQUIRED_ATTRIBUTES, IF_OPTIONAL_ATTRIBUTES); condition = (String) anAttributes.get( IF_CONDITION_ATTRIBUTE ); }; @@ -948,30 +1007,33 @@ public class DefaultProducerNodeBuilders { public static class RSSProducerNodeBuilder extends AbstractProducerNodeBuilder { private final static String RSS_KEY_ATTRIBUTE = KEY_ATTRIBUTE; private final static String RSS_URL_ATTRIBUTE = URL_ATTRIBUTE; + private final static String RSS_ENCODING_ATTRIBUTE = "encoding"; private final static String RSS_VERSION_ATTRIBUTE = "version"; private final static String[] RSS_REQUIRED_ATTRIBUTES = { RSS_KEY_ATTRIBUTE, RSS_URL_ATTRIBUTE }; - private final static String[] RSS_OPTIONAL_ATTRIBUTES = { RSS_VERSION_ATTRIBUTE }; + private final static String[] RSS_OPTIONAL_ATTRIBUTES = { RSS_VERSION_ATTRIBUTE, RSS_ENCODING_ATTRIBUTE }; private final static String[] RSS_SUBNODES = { }; private String key; private String url; private String version; + private String encoding; public RSSProducerNodeBuilder() { super(RSS_SUBNODES); } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, RSS_REQUIRED_ATTRIBUTES, RSS_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, RSS_REQUIRED_ATTRIBUTES, RSS_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get( RSS_KEY_ATTRIBUTE ); url = (String) anAttributes.get( RSS_URL_ATTRIBUTE ); - version = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_VERSION_ATTRIBUTE, "1.0"); + version = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_VERSION_ATTRIBUTE, "1.0"); + encoding = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RSS_ENCODING_ATTRIBUTE, null); }; public ProducerNode constructNode() { - return new RSSProducerNode(key, url, version); + return new RSSProducerNode(key, url, version, encoding); }; } @@ -997,12 +1059,12 @@ public class DefaultProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, RDF_AGGREGATOR_REQUIRED_ATTRIBUTES, RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, RDF_AGGREGATOR_REQUIRED_ATTRIBUTES, RDF_AGGREGATOR_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get( RDF_AGGREGATOR_KEY_ATTRIBUTE ); source = (String) anAttributes.get( RDF_AGGREGATOR_SOURCE_ATTRIBUTE ); - order = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_SOURCE_ATTRIBUTE, ""); - filter = mir.util.xml.XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_FILTER_ATTRIBUTE, ""); + order = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_SOURCE_ATTRIBUTE, ""); + filter = XMLReaderTool.getStringAttributeWithDefault(anAttributes, RDF_AGGREGATOR_FILTER_ATTRIBUTE, ""); }; public ProducerNode constructNode() { @@ -1067,7 +1129,7 @@ public class DefaultProducerNodeBuilders { }; public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes()); + XMLReaderTool.checkAttributeSet(anAttributes.keySet(), definition.getRequiredAttributes(), definition.getOptionalAttributes()); Iterator i = anAttributes.entrySet().iterator(); while (i.hasNext()) { diff --git a/source/mir/producer/reader/ProducerConfigReader.java b/source/mir/producer/reader/ProducerConfigReader.java index b3ffdae7..631573f9 100755 --- a/source/mir/producer/reader/ProducerConfigReader.java +++ b/source/mir/producer/reader/ProducerConfigReader.java @@ -29,14 +29,15 @@ */ package mir.producer.reader; +import java.io.File; +import java.io.Reader; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.Vector; -import java.io.File; import mir.producer.CompositeProducerNode; import mir.producer.ProducerFactory; @@ -55,6 +56,24 @@ public class ProducerConfigReader { super(); }; + public void parse(Reader aReader, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure { + try { + builderLibrary = aBuilderLibrary; + scriptedNodeBuilderLibrary = new ProducerNodeBuilderLibrary(); + + XMLParserEngine.getInstance().parse("", aReader, new RootSectionHandler(aProducerFactories)); + + } + catch (Throwable e) { + Throwable root = ExceptionFunctions.traceCauseException(e); + + if ((root instanceof XMLParserExc) && ((XMLParserExc) root).getHasLocation()) { + XMLParserExc f = (XMLParserExc) root; + throw new ProducerConfigFailure(f.getMessage()+" on line " + f.getLineNr()+", column " + f.getColumnNr(), e); + } + throw new ProducerConfigFailure(root); + } + } public void parse(File aFile, ProducerNodeBuilderLibrary aBuilderLibrary, List aProducerFactories) throws ProducerConfigFailure { try { builderLibrary = aBuilderLibrary; @@ -237,7 +256,7 @@ public class ProducerConfigReader { public ProducerVerbsSectionHandler() { verbNodes = new HashMap(); - verbs = new Vector(); + verbs = new ArrayList(); defaultVerb = null; } diff --git a/source/mir/producer/reader/ScriptedProducerFactory.java b/source/mir/producer/reader/ScriptedProducerFactory.java index 1a939a1b..1964b3cd 100755 --- a/source/mir/producer/reader/ScriptedProducerFactory.java +++ b/source/mir/producer/reader/ScriptedProducerFactory.java @@ -87,7 +87,7 @@ public class ScriptedProducerFactory implements ProducerFactory { return new NodedProducer(rootNode, aVerb, aStartingValues); }; - public Iterator verbs() { - return verbs.iterator(); + public List verbs() { + return verbs; } } \ No newline at end of file diff --git a/source/mir/rss/RSS091Reader.java b/source/mir/rss/RSS091Reader.java index 18bc0af8..a6556b72 100755 --- a/source/mir/rss/RSS091Reader.java +++ b/source/mir/rss/RSS091Reader.java @@ -36,8 +36,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; -import mir.util.xml.*; +import mir.util.HTTPClientHelper; +import mir.util.xml.*; import mir.util.xml.XMLParserEngine; /** @@ -95,15 +96,49 @@ public class RSS091Reader { } } - public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure { + public RSSData parseInputStream(InputStream aStream, String anEncoding) throws RSSExc, RSSFailure { try { - InputStream inputStream = (InputStream) new URL(anUrl).getContent(new Class[] {InputStream.class}); + RSSData result = new RSSData(); + XMLParserEngine.getInstance().parse("html", aStream, anEncoding, new RootSectionHandler(result)); + return result; + } + catch (Throwable t) { + throw new RSSFailure(t); + } + } + + public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure { + try { + HTTPClientHelper httpClientHelper = new HTTPClientHelper(); + InputStream inputStream = httpClientHelper.getUrl(anUrl); + if (inputStream==null) throw new RSSExc("RSSChannel.parseUrl: Can't get url content"); - return parseInputStream(inputStream); + RSSData theRSSData = parseInputStream(inputStream); + httpClientHelper.releaseHTTPConnection(); + return theRSSData; + + } + catch (Throwable t) { + throw new RSSFailure(t); + } + } + + public RSSData parseUrl(String anUrl, String anEncoding) throws RSSExc, RSSFailure { + try { + HTTPClientHelper httpClientHelper = new HTTPClientHelper(); + InputStream inputStream = httpClientHelper.getUrl(anUrl); + + if (inputStream==null) + throw new RSSExc("RSSChannel.parseUrl: Can't get url content"); + + RSSData theRSSData = parseInputStream(inputStream, anEncoding); + httpClientHelper.releaseHTTPConnection(); + return theRSSData; } + catch (Throwable t) { throw new RSSFailure(t); } @@ -223,7 +258,6 @@ public class RSS091Reader { public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc { String tag = aTag.getLocalName(); - System.out.println(tag); if (mappedItemProperties.containsKey(tag)) { currentTag=(String) mappedItemProperties.get(tag); diff --git a/source/mir/rss/RSSAggregator.java b/source/mir/rss/RSSAggregator.java index a7b48d21..8b44191e 100755 --- a/source/mir/rss/RSSAggregator.java +++ b/source/mir/rss/RSSAggregator.java @@ -30,9 +30,9 @@ package mir.rss; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Vector; public class RSSAggregator { private String orderBy; @@ -46,7 +46,7 @@ public class RSSAggregator { orderBy = anOrderBy; orderReversed = anOrderReversed; capacity = aCapacity; - items = new Vector(); + items = new ArrayList(); selectionValue = aSelectionValue; selectionField = aSelectionField; } diff --git a/source/mir/rss/RSSData.java b/source/mir/rss/RSSData.java index a5e6181c..d858aed0 100755 --- a/source/mir/rss/RSSData.java +++ b/source/mir/rss/RSSData.java @@ -32,7 +32,7 @@ package mir.rss; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; +import java.util.ArrayList; public class RSSData { private List resources; @@ -40,7 +40,7 @@ public class RSSData { private Map identifierToResource; protected RSSData() { - resources = new Vector(); + resources = new ArrayList(); rdfClassToResources = new HashMap(); identifierToResource = new HashMap(); } @@ -53,7 +53,7 @@ public class RSSData { resources.add(aResource); List resourcesForClass = (List) rdfClassToResources.get(aResource.getRdfClass()); if (resourcesForClass==null) { - resourcesForClass = new Vector(); + resourcesForClass = new ArrayList(); rdfClassToResources.put(aResource.getRdfClass(), resourcesForClass); } resourcesForClass.add(aResource); diff --git a/source/mir/rss/RSSReader.java b/source/mir/rss/RSSReader.java index 1d7bf402..6d89d49c 100755 --- a/source/mir/rss/RSSReader.java +++ b/source/mir/rss/RSSReader.java @@ -30,13 +30,13 @@ package mir.rss; import java.io.InputStream; -import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; import mir.util.DateTimeFunctions; +import mir.util.HTTPClientHelper; import mir.util.xml.XMLParserEngine; import mir.util.xml.XMLParserExc; import mir.util.xml.XMLParserFailure; @@ -77,7 +77,7 @@ public class RSSReader { private Map moduleToPrefix; public RSSReader() { - modules = new Vector(); + modules = new ArrayList(); namespaceURItoModule = new HashMap(); moduleToPrefix = new HashMap(); @@ -118,7 +118,19 @@ public class RSSReader { public RSSData parseInputStream(InputStream aStream) throws RSSExc, RSSFailure { try { RSSData result = new RSSData(); - XMLParserEngine.getInstance().parse("xml.namespaceaware", aStream, new RootSectionHandler(result)); + XMLParserEngine.getInstance().parse("xml", aStream, new RootSectionHandler(result)); + + return result; + } + catch (Throwable t) { + throw new RSSFailure(t); + } + } + + public RSSData parseInputStream(InputStream aStream, String anEncoding) throws RSSExc, RSSFailure { + try { + RSSData result = new RSSData(); + XMLParserEngine.getInstance().parse("xml", aStream, anEncoding, new RootSectionHandler(result)); return result; } @@ -129,12 +141,30 @@ public class RSSReader { public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure { try { - InputStream inputStream = (InputStream) new URL(anUrl).getContent(new Class[] {InputStream.class}); + HTTPClientHelper httpClientHelper = new HTTPClientHelper(); + InputStream inputStream = httpClientHelper.getUrl(anUrl); + if (inputStream==null) + throw new RSSExc("RSSChannel.parseUrl: Can't get url content"); + RSSData theRSSData = parseInputStream(inputStream); + httpClientHelper.releaseHTTPConnection(); + return theRSSData; + } + catch (Throwable t) { + throw new RSSFailure(t); + } + } + + public RSSData parseUrl(String anUrl, String anEncoding) throws RSSExc, RSSFailure { + try { + HTTPClientHelper httpClientHelper = new HTTPClientHelper(); + InputStream inputStream = httpClientHelper.getUrl(anUrl); if (inputStream==null) throw new RSSExc("RSSChannel.parseUrl: Can't get url content"); - return parseInputStream(inputStream); + RSSData theRSSData = parseInputStream(inputStream, anEncoding); + httpClientHelper.releaseHTTPConnection(); + return theRSSData; } catch (Throwable t) { throw new RSSFailure(t); @@ -235,7 +265,7 @@ public class RSSReader { List value = (List) aResource.get(makeQualifiedName(aTag)); if (value==null) { - value = new Vector(); + value = new ArrayList(); aResource.set(makeQualifiedName(aTag), value); } @@ -349,7 +379,7 @@ public class RSSReader { private List items; public RDFCollectionSectionHandler() { - items = new Vector(); + items = new ArrayList(); } public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc { @@ -451,7 +481,7 @@ public class RSSReader { private List items; public RDFSequenceSectionHandler() { - items = new Vector(); + items = new ArrayList(); } public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc { diff --git a/source/mir/servlet/AbstractServlet.java b/source/mir/servlet/AbstractServlet.java index 90aff294..55648f35 100755 --- a/source/mir/servlet/AbstractServlet.java +++ b/source/mir/servlet/AbstractServlet.java @@ -46,27 +46,19 @@ import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; import mircoders.global.MirGlobal; -import com.codestudio.util.JDBCPool; -import com.codestudio.util.JDBCPoolMetaData; -import com.codestudio.util.SQLManager; - /** * Title: Mir * Description: Abstract servlet-class * Copyright: Copyright (c) 2001, 2002 * Company: Mir-coders group * @author idfx, the Mir-coders group - * @version $Id: AbstractServlet.java,v 1.30.2.6 2003/12/03 18:10:45 rk Exp $ + * @version $Id: AbstractServlet.java,v 1.30.2.7 2004/11/21 22:07:13 zapata Exp $ */ public abstract class AbstractServlet extends HttpServlet { - //protected static String lang; protected LoggerWrapper logger; protected MirPropertiesConfiguration configuration; - /** - * Constructor for AbstractServlet. - */ public AbstractServlet() { super(); } @@ -76,6 +68,7 @@ public abstract class AbstractServlet extends HttpServlet { // //this needs to be done here and not per page (via meta tags) as some //browsers have problems w/ it per-page -mh + aResponse.setHeader("Pragma", "no-cache"); aResponse.setDateHeader("Expires", 0); aResponse.setHeader("Cache-Control", "no-cache"); @@ -95,13 +88,13 @@ public abstract class AbstractServlet extends HttpServlet { * Get the session-bound language */ protected String getLanguage(HttpServletRequest aRequest, HttpSession session) { - String lang = (String) session.getAttribute("language"); + String language = (String) session.getAttribute("language"); - if (lang == null || lang.length()==0) { - lang = getAcceptLanguage(aRequest); + if (language == null || language.length()==0) { + language = getAcceptLanguage(aRequest); } - return lang; + return language; } /** @@ -109,20 +102,20 @@ public abstract class AbstractServlet extends HttpServlet { * this supersedes getLanguage for the new i18n */ public Locale getLocale(HttpServletRequest aRequest) { - Locale loc = null; + Locale locale = null; HttpSession session = aRequest.getSession(false); if (session != null) { // session can be null in case of logout - loc = (Locale) session.getAttribute("locale"); + locale = (Locale) session.getAttribute("locale"); } // if there is nothing in the session get it fron the accept-language - if (loc == null) { - loc = aRequest.getLocale(); + if (locale == null) { + locale = aRequest.getLocale(); } - logger.debug("getting locale: " + loc.getLanguage()); + logger.debug("getting locale: " + locale.getLanguage()); - return loc; + return locale; } /** @@ -160,47 +153,10 @@ public abstract class AbstractServlet extends HttpServlet { throw new ServletException("can't get localizer: " + t.toString()); } - String dbUser = configuration.getString("Database.Username"); - String dbPassword = configuration.getString("Database.Password"); - String dbHost = configuration.getString("Database.Host"); - String dbPort = configuration.getString("Database.Port"); - String dbAdapName = configuration.getString("Database.Adaptor"); - String dbName = configuration.getString("Database.Name"); - String dbDriver = configuration.getString("Database.Driver"); - String dbUrl = "jdbc:postgresql://"+dbHost+":"+dbPort+"/"+dbName; - int dbMin = configuration.getInteger("Database.poolMin", 1); - int dbMax = configuration.getInteger("Database.poolMax", 10); - - JDBCPoolMetaData meta = new JDBCPoolMetaData(); - meta.setDbname(dbName); - meta.setDriver(dbDriver); - meta.setURL(dbUrl); - meta.setUserName(dbUser); - meta.setPassword(dbPassword); - meta.setJNDIName("mir"); - meta.setMaximumSize(dbMax); - meta.setMinimumSize(dbMin); - meta.setPoolPreparedStatements(false); - meta.setCacheEnabled(false); - meta.setCacheSize(15); - meta.setDebugging(false); - - SQLManager manager = SQLManager.getInstance(); - - JDBCPool pool = null; - if (manager != null) { - pool = manager.createPool(meta); - } - - if (pool==null) { - logger.fatal("Can't get pool!"); - throw new ServletException("Can't get pool!" ); - } - Connection connection; try { - connection = pool.requestConnection(); - JDBCPool.closeConnection(connection); + connection = MirGlobal.getDatabaseEngine().obtainConnection(); + MirGlobal.getDatabaseEngine().releaseConnection(connection); } catch (Throwable t) { logger.fatal("Can't connect to database: " + t.toString()); @@ -220,7 +176,6 @@ public abstract class AbstractServlet extends HttpServlet { } catch (NoSuchMethodException e) { // TODO set the encoding in a zapata-way -// logger.warn("set encoding not yet implemented: " + e.getMessage()); } catch (SecurityException e) { logger.error(e.getMessage()); @@ -256,9 +211,6 @@ public abstract class AbstractServlet extends HttpServlet { /** * Selects the language for the response. - * - * @param session - * @param aRequest */ protected void checkLanguage(HttpSession aSession, HttpServletRequest aRequest) { String requestLanguage = aRequest.getParameter("language"); diff --git a/source/mir/servlet/ServletModule.java b/source/mir/servlet/ServletModule.java index 3eda4993..d2d89e8f 100755 --- a/source/mir/servlet/ServletModule.java +++ b/source/mir/servlet/ServletModule.java @@ -34,22 +34,23 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; import mir.entity.adapter.EntityAdapterEngine; import mir.entity.adapter.EntityAdapterModel; import mir.log.LoggerWrapper; import mir.module.AbstractModule; +import mir.module.ModuleExc; import mir.storage.StorageObject; import mir.util.HTTPRequestParser; import mir.util.URLBuilder; import mircoders.global.MirGlobal; import mircoders.servlet.ServletHelper; +import mircoders.localizer.MirLocalizerExc; +import multex.Failure; /** * @@ -64,8 +65,8 @@ import mircoders.servlet.ServletHelper; public abstract class ServletModule { public String defaultAction; protected LoggerWrapper logger; - protected MirPropertiesConfiguration configuration; - protected Locale fallbackLocale; + protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); + private static Locale fallbackLocale = new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), ""); protected AbstractModule mainModule; protected String definition; @@ -79,15 +80,16 @@ public abstract class ServletModule { public ServletModule(){ definition = null; - model = null; - try { - configuration = MirPropertiesConfiguration.instance(); + model = MirGlobal.localizer().dataModel().adapterModel(); } - catch (PropertiesConfigExc e) { - throw new RuntimeException("Can't get configuration: " + e.getMessage()); + catch (MirLocalizerExc e) { + logger.error("Can't create model: " + e.toString()); + throw new ServletModuleFailure("Can't retrieve model", e); } + + listGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".ListTemplate"); editGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".EditTemplate"); deleteConfirmationGenerator = configuration.getString("ServletModule."+getOperationModuleName()+".DeleteConfirmationTemplate"); @@ -95,7 +97,6 @@ public abstract class ServletModule { configuration.getInt("ServletModule."+getOperationModuleName()+".ListSize", configuration.getInt("ServletModule.Default.ListSize", 20)); - fallbackLocale = new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), ""); } @@ -113,19 +114,21 @@ public abstract class ServletModule { } /** - * Get the module name - * - * @return + * Return the module name */ protected String getOperationModuleName() { return getClass().getName().substring((new String("mircoders.servlet.ServletModule")).length()); } + public static Locale[] getLocales(HttpServletRequest aRequest) { + return new Locale[] { getLocale(aRequest), fallbackLocale }; + } + /** - * get the locale either from the session or the accept-language header ot the request + * Return the locale either from the session or the accept-language header ot the request * this supersedes getLanguage for the new i18n */ - public Locale getLocale(HttpServletRequest aRequest) { + public static Locale getLocale(HttpServletRequest aRequest) { Locale loc = null; HttpSession session = aRequest.getSession(false); if (session != null) { @@ -156,7 +159,7 @@ public abstract class ServletModule { public String getDefaultListOrdering() { if (mainModule!=null && mainModule.getStorageObject()!=null){ - if (mainModule.getStorageObject().getFields().contains("webdb_create")) + if (mainModule.getStorageObject().getFieldNames().contains("webdb_create")) return "webdb_create desc"; } @@ -164,29 +167,7 @@ public abstract class ServletModule { } /** - * - * @param aResponse - * @param aQuery - * @throws ServletModuleExc - * @throws ServletModuleFailure - */ - public void redirect(HttpServletResponse aResponse, String aQuery) throws ServletModuleExc, ServletModuleFailure { - try { - aResponse.sendRedirect(aResponse.encodeRedirectURL(MirPropertiesConfiguration.instance().getString("RootUri") + "/servlet/Mir?"+aQuery)); - } - catch (Throwable t) { - throw new ServletModuleFailure("ServletModule.redirect: " +t.getMessage(), t); - } - } - - /** - * Generic list method - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic list servlet method */ public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc @@ -209,7 +190,7 @@ public abstract class ServletModule { int count; try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); List list = EntityAdapterEngine.retrieveAdapterList(model, definition, aWhereClause, anOrderByClause, nrEntitiesPerListPage, anOffset); @@ -275,10 +256,9 @@ public abstract class ServletModule { public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, Object anObject, boolean anIsNew, String anId) throws ServletModuleExc { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); URLBuilder urlBuilder = new URLBuilder(); - EntityAdapterModel model; try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); responseData.put("module", getOperationModuleName()); responseData.put("entity", anObject); @@ -303,22 +283,15 @@ public abstract class ServletModule { } } - /** - * Generic add method - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic add servlet method */ public void add(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { Map object = new HashMap(); - Iterator i = mainModule.getStorageObject().getFields().iterator(); + Iterator i = mainModule.getStorageObject().getFieldNames().iterator(); while (i.hasNext()) object.put(i.next(), ""); @@ -332,27 +305,13 @@ public abstract class ServletModule { } /** - * Method called when the user edits an object. - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic edit servlet method */ public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { edit(aRequest, aResponse, aRequest.getParameter("id")); } /** - * Generic edit method - * - * @param aRequest - * @param aResponse - * @param anIdentifier - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure */ public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse, String anIdentifier) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { @@ -365,13 +324,7 @@ public abstract class ServletModule { } /** - * Generic update method - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic update servlet method */ public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { @@ -387,7 +340,7 @@ public abstract class ServletModule { String returnUrl = requestParser.getParameter("returnurl"); if (returnUrl!=null) { - redirect(aResponse, returnUrl); + ServletHelper.redirect(aResponse, returnUrl); } else { edit(aRequest, aResponse, id); @@ -399,13 +352,7 @@ public abstract class ServletModule { } /** - * Generic insert method - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic insert servlet method */ public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { @@ -421,7 +368,7 @@ public abstract class ServletModule { String returnUrl = requestParser.getParameter("returnurl"); if (returnUrl!=null) { - redirect(aResponse, returnUrl); + ServletHelper.redirect(aResponse, returnUrl); } else { edit(aRequest, aResponse, id); @@ -432,33 +379,33 @@ public abstract class ServletModule { } } + /** + * + */ public String processInstertedObject(Map anObject, HttpServletRequest aRequest, HttpServletResponse aResponse) { try { return mainModule.add(anObject); } - catch (Throwable t) { + catch (ModuleExc t) { throw new ServletModuleFailure(t); } }; /** - * - * @param aRequest - * @param aResponse + * Generic delete confirmation servlet method */ public void confirmdelete(HttpServletRequest aRequest, HttpServletResponse aResponse) { try { String idParam = aRequest.getParameter("id"); String confirmParam = aRequest.getParameter("confirm"); - String cancelParam = aRequest.getParameter("cancel"); if (confirmParam != null && !confirmParam.equals("")) { mainModule.deleteById(idParam); logAdminUsage(aRequest, idParam, "object deleted"); - redirect(aResponse, aRequest.getParameter("okurl")); + ServletHelper.redirect(aResponse, aRequest.getParameter("okurl")); } else - redirect(aResponse, aRequest.getParameter("cancelurl")); + ServletHelper.redirect(aResponse, aRequest.getParameter("cancelurl")); } catch (Throwable t) { throw new ServletModuleFailure(t); @@ -466,12 +413,7 @@ public abstract class ServletModule { } /** - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure + * Generic delete servlet method */ public void delete(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { @@ -481,7 +423,7 @@ public abstract class ServletModule { if (idParam == null) throw new ServletModuleExc("Invalid call to delete: no id supplied"); - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); responseData.put("module", getOperationModuleName()); responseData.put("id", idParam); @@ -496,11 +438,6 @@ public abstract class ServletModule { } /** - * Wenn die abgeleitete Klasse diese Methode ueberschreibt und einen String mit einem - * Methodennamen zurueckliefert, dann wird diese Methode bei fehlender Angabe des - * doParameters ausgefuehrt. - * - * @return Name der Default-Action */ public String defaultAction() { return defaultAction; @@ -515,30 +452,23 @@ public abstract class ServletModule { public Map getIntersectingValues(HttpServletRequest aRequest, StorageObject theStorage) throws ServletModuleExc, ServletModuleFailure { - try { - HTTPRequestParser parser; - List theFieldList; + HTTPRequestParser parser; + List theFieldList; - parser = new HTTPRequestParser(aRequest); + parser = new HTTPRequestParser(aRequest); - theFieldList = theStorage.getFields(); + theFieldList = theStorage.getFieldNames(); - Map withValues = new HashMap(); - String aField, aValue; + Map withValues = new HashMap(); + String aField, aValue; - for (int i = 0; i < theFieldList.size(); i++) { - aField = (String) theFieldList.get(i); - - aValue = parser.getParameter(aField); - if (aValue != null) - withValues.put(aField, aValue); - } - return withValues; - } - catch (Throwable e) { - e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + for (int i = 0; i < theFieldList.size(); i++) { + aField = (String) theFieldList.get(i); - throw new ServletModuleFailure( "ServletModule.getIntersectingValues: " + e.getMessage(), e); + aValue = parser.getParameter(aField); + if (aValue != null) + withValues.put(aField, aValue); } + return withValues; } } \ No newline at end of file diff --git a/source/mir/session/CommonsUploadedFileAdapter.java b/source/mir/session/CommonsUploadedFileAdapter.java index 4b607ca0..968c0042 100755 --- a/source/mir/session/CommonsUploadedFileAdapter.java +++ b/source/mir/session/CommonsUploadedFileAdapter.java @@ -29,10 +29,12 @@ */ package mir.session; -import java.io.InputStream; - import org.apache.commons.fileupload.FileItem; +import java.io.File; +import java.io.InputStream; +import java.io.IOException; + public class CommonsUploadedFileAdapter implements UploadedFile { private FileItem fileItem; @@ -40,14 +42,25 @@ public class CommonsUploadedFileAdapter implements UploadedFile { fileItem = aFileItem; } - public InputStream getInputStream() throws SessionExc, SessionFailure{ + public void writeToFile(File aFile) throws SessionExc, SessionFailure { + try { + aFile.getParentFile().mkdirs(); + fileItem.write(aFile); + } + catch (Exception e) { + e.printStackTrace(); + throw new SessionFailure(e); + } + } + + public InputStream getInputStream() throws SessionExc, SessionFailure { try { return fileItem.getInputStream(); } - catch (Throwable t) { - throw new SessionFailure(t); + catch (IOException e) { + throw new SessionFailure(e); } - }; + } public String getFileName() { return fileItem.getName(); diff --git a/source/mir/session/HTTPAdapters.java b/source/mir/session/HTTPAdapters.java index 5dcc5107..08c82210 100755 --- a/source/mir/session/HTTPAdapters.java +++ b/source/mir/session/HTTPAdapters.java @@ -29,20 +29,19 @@ */ package mir.session; -import java.util.Arrays; -import java.util.List; -import java.util.Vector; - +import java.util.*; +import java.net.InetAddress; +import java.net.UnknownHostException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import mir.util.HTTPParsedRequest; - import org.apache.commons.fileupload.FileItem; public class HTTPAdapters { public static class HTTPRequestAdapter implements Request { private HttpServletRequest request; + private String cachedHostName = null; public HTTPRequestAdapter(HttpServletRequest aRequest) { request = aRequest; @@ -52,6 +51,22 @@ public class HTTPAdapters { if (aHeaderName.equals("ip")) return request.getRemoteAddr(); + if (aHeaderName.equals("hostname")) { + if (aHeaderName.equals("hostname")) { + if (cachedHostName==null) { + try { + cachedHostName = InetAddress.getByName(request.getRemoteAddr()).getHostName(); + } + catch (UnknownHostException e) { + cachedHostName = request.getRemoteAddr(); + } + } + + return cachedHostName; + } + + } + return request.getHeader(aHeaderName); }; @@ -59,8 +74,22 @@ public class HTTPAdapters { return request.getParameter(aName); }; + public List getPrefixedParameterNames(String aPrefix) { + List result = new ArrayList(); + + Enumeration enumeration = request.getParameterNames(); + while (enumeration.hasMoreElements()) { + String name = (String) enumeration.nextElement(); + if (name.startsWith(aPrefix)) { + result.add(name); + } + } + + return result; + }; + public List getUploadedFiles() { - return new Vector(); + return Collections.EMPTY_LIST; }; public List getParameters(String aName) { @@ -74,6 +103,7 @@ public class HTTPAdapters { public static class HTTPParsedRequestAdapter implements Request { private HTTPParsedRequest request; + private String cachedHostName = null; public HTTPParsedRequestAdapter(HTTPParsedRequest aRequest) { request = aRequest; @@ -83,8 +113,21 @@ public class HTTPAdapters { if (aHeaderName.equals("ip")) return request.getRequest().getRemoteAddr(); + if (aHeaderName.equals("hostname")) { + if (cachedHostName==null) { + try { + cachedHostName = InetAddress.getByName(request.getRequest().getRemoteAddr()).getHostName(); + } + catch (UnknownHostException e) { + cachedHostName = request.getRequest().getRemoteAddr(); + } + } + + return cachedHostName; + } + return request.getHeader(aHeaderName); - }; + } public String getParameter(String aName) { return request.getParameter(aName); @@ -94,8 +137,23 @@ public class HTTPAdapters { return request.getParameterList(aName); }; + public List getPrefixedParameterNames(String aPrefix) { + List result = new ArrayList(); + + Iterator i = request.getParameterNames().iterator(); + + while (i.hasNext()) { + String name = (String) i.next(); + if (name.startsWith(aPrefix)) { + result.add(name); + } + } + + return result; + }; + public List getUploadedFiles() { - List result = new Vector(); + List result = new ArrayList(); List files = request.getFiles(); for (int i=0; iInputStream to access the uploaded content + */ + public InputStream getInputStream() throws SessionExc, SessionFailure; + + /** + * Return the filename supplied by the uploader if available. + * null if no filename is available. + */ + public String getFileName(); + + /** + * Return the field name associated with the uploaded file + */ + public String getFieldName(); + + /** + * Return the content type (if it's present) of the uploaded file. + * null if no content type is available. + */ + public String getContentType(); } \ No newline at end of file diff --git a/source/mir/storage/Database.java b/source/mir/storage/Database.java index a236a482..98767916 100755 --- a/source/mir/storage/Database.java +++ b/source/mir/storage/Database.java @@ -29,53 +29,29 @@ */ package mir.storage; -import java.io.IOException; -import java.io.InputStreamReader; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Timestamp; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; -import java.util.Vector; - import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; import mir.entity.Entity; import mir.entity.EntityList; import mir.entity.StorableObjectEntity; import mir.log.LoggerWrapper; import mir.misc.StringUtil; -import mir.storage.store.ObjectStore; -import mir.storage.store.StorableObject; -import mir.storage.store.StoreContainerType; -import mir.storage.store.StoreIdentifier; -import mir.storage.store.StoreUtil; +import mir.storage.store.*; import mir.util.JDBCStringRoutines; +import mircoders.global.MirGlobal; -import com.codestudio.util.SQLManager; - +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.sql.*; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; /** - * Diese Klasse implementiert die Zugriffsschicht auf die Datenbank. - * Alle Projektspezifischen Datenbankklassen erben von dieser Klasse. - * In den Unterklassen wird im Minimalfall nur die Tabelle angegeben. - * Im Konfigurationsfile findet sich eine Verweis auf den verwendeten - * Treiber, Host, User und Passwort, ueber den der Zugriff auf die - * Datenbank erfolgt. + * Implements database access. * - * @version $Id: Database.java,v 1.44.2.22 2004/02/08 21:05:01 zapata Exp $ + * @version $Id: Database.java,v 1.44.2.23 2004/11/21 22:07:13 zapata Exp $ * @author rk * */ @@ -85,16 +61,15 @@ public class Database implements StorageObject { private static final int _millisPerHour = 60 * 60 * 1000; protected LoggerWrapper logger; + protected MirPropertiesConfiguration configuration; protected String mainTable; protected String primaryKeySequence = null; protected String primaryKeyField = "id"; - protected boolean evaluatedMetaData = false; - protected ArrayList metadataFields; - protected ArrayList metadataLabels; - protected ArrayList metadataNotNullFields; - protected int[] metadataTypes; + protected List fieldNames; + protected int[] fieldTypes; + protected Class theEntityClass; protected boolean hasTimestamp = true; private int defaultLimit; @@ -112,12 +87,7 @@ public class Database implements StorageObject { * erzeugt. */ public Database() throws StorageObjectFailure { - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new StorageObjectFailure(e); - } + configuration = MirPropertiesConfiguration.instance(); logger = new LoggerWrapper("Database"); timezone = TimeZone.getTimeZone(configuration.getString("Mir.DefaultTimezone")); internalDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -192,39 +162,14 @@ public class Database implements StorageObject { } /** - * Liefert Feldtypen der Felder der Tabelle zurueck (s.a. java.sql.Types) - * @return int-Array mit den Typen der Felder - * @exception StorageObjectFailure - */ - public int[] getTypes() throws StorageObjectFailure { - if (metadataTypes == null) { - get_meta_data(); - } - - return metadataTypes; - } - - /** - * Liefert eine Liste der Labels der Tabellenfelder + * {@inheritDoc} */ - public List getLabels() throws StorageObjectFailure { - if (metadataLabels == null) { - get_meta_data(); + public List getFieldNames() throws StorageObjectFailure { + if (fieldNames == null) { + retrieveMetaData(); } - return metadataLabels; - } - - /** - * Liefert eine Liste der Felder der Tabelle - * @return ArrayList mit Feldern - */ - public List getFields() throws StorageObjectFailure { - if (metadataFields == null) { - get_meta_data(); - } - - return metadataFields; + return fieldNames; } /** @@ -388,7 +333,7 @@ public class Database implements StorageObject { } Statement stmt = null; - Connection con = getPooledCon(); + Connection con = obtainConnection(); Entity returnEntity = null; try { @@ -401,10 +346,6 @@ public class Database implements StorageObject { rs = executeSql(stmt, selectSql); if (rs != null) { - if (evaluatedMetaData == false) { - evalMetaData(rs.getMetaData()); - } - if (rs.next()) { returnEntity = makeEntityFromResultSet(rs); } @@ -448,25 +389,12 @@ public class Database implements StorageObject { return selectByWhereClause( mainTablePrefix, extraTables, aWhereClause, "", 0, defaultLimit); } - /** - * select-Operator um Datensaetze zu bekommen, die key = value erfuellen. - * @param aField Datenbankfeld der Bedingung. - * @param aValue Wert die der key anehmen muss. - * @return EntityList mit den gematchten Entities - */ public EntityList selectByFieldValue(String aField, String aValue) throws StorageObjectFailure { return selectByFieldValue(aField, aValue, 0); } - /** - * select-Operator um Datensaetze zu bekommen, die key = value erfuellen. - * @param aField Datenbankfeld der Bedingung. - * @param aValue Wert die der key anehmen muss. - * @param offset Gibt an ab welchem Datensatz angezeigt werden soll. - * @return EntityList mit den gematchten Entities - */ public EntityList selectByFieldValue(String aField, String aValue, int offset) throws StorageObjectFailure { - return selectByWhereClause(aField + "=" + aValue, offset); + return selectByWhereClause(aField + "='" + JDBCStringRoutines.escapeStringLiteral(aValue)+"'", offset); } /** @@ -545,39 +473,41 @@ public class Database implements StorageObject { * select-Operator returns EntityList with matching rows in Database. * @param aWhereClause where-Clause * @param anOrderByClause orderBy-Clause - * @param offset ab welchem Datensatz - * @param limit wieviele Datens?tze + * @param anOffset ab welchem Datensatz + * @param aLimit wieviele Datens?tze * @return EntityList mit den gematchten Entities * @exception StorageObjectFailure */ - public EntityList selectByWhereClause(String mainTablePrefix, List extraTables, + public EntityList selectByWhereClause( + String aMainTablePrefix, List anExtraTables, String aWhereClause, String anOrderByClause, - int offset, int limit) throws StorageObjectFailure { + int anOffset, int aLimit) throws StorageObjectFailure { - // TODO get rid of emtpy Strings in extraTables - // make extraTables null, if single empty String in it + // TODO get rid of emtpy Strings in anExtraTables + // make anExtraTables null, if single empty String in it // cause StringUtil.splitString puts in emptyString - if (extraTables != null && ((String)extraTables.get(0)).trim().equals("")) - { - logger.debug("+++ made extraTables to null!"); - extraTables=null; - } - String useTable = mainTable; - String selectStar = "*"; - if (mainTablePrefix!=null && mainTablePrefix.trim().length()>0) { - useTable+=" "+mainTablePrefix; - selectStar=mainTablePrefix.trim() + ".*"; - } + if (anExtraTables!=null && ((String) anExtraTables.get(0)).trim().equals("")){ + logger.debug("+++ made anExtraTables to null!"); + anExtraTables=null; + } + + String useTable = mainTable; + String selection = "*"; + + if (aMainTablePrefix != null && aMainTablePrefix.trim().length() > 0) { + useTable += " " + aMainTablePrefix; + selection = aMainTablePrefix.trim() + ".*"; + } // check o_store for entitylist // only if no relational select - if (extraTables==null) { + if (anExtraTables==null) { if (StoreUtil.extendsStorableEntity(theEntityClass)) { StoreIdentifier searchSid = new StoreIdentifier(theEntityClass, StoreContainerType.STOC_TYPE_ENTITYLIST, StoreUtil.getEntityListUniqueIdentifierFor(mainTable, - aWhereClause, anOrderByClause, offset, limit)); + aWhereClause, anOrderByClause, anOffset, aLimit)); EntityList hit = (EntityList) o_store.use(searchSid); if (hit != null) { @@ -588,9 +518,10 @@ public class Database implements StorageObject { // local EntityList theReturnList = null; - Connection con = null; - Statement stmt = null; - ResultSet rs; + Connection connection = null; + Statement statement = null; + ResultSet resultSet; + int offsetCount = 0; int count = 0; @@ -603,14 +534,14 @@ public class Database implements StorageObject { StringBuffer countSql = new StringBuffer("select count(*) from ").append(useTable); StringBuffer selectSql = - new StringBuffer("select "+selectStar+" from ").append(useTable); + new StringBuffer("select "+selection+" from ").append(useTable); // append extratables, if necessary - if (extraTables!=null) { - for (int i=0;i < extraTables.size();i++) { - if (!extraTables.get(i).equals("")) { - countSql.append( ", " + extraTables.get(i)); - selectSql.append( ", " + extraTables.get(i)); + if (anExtraTables!=null) { + for (int i=0;i < anExtraTables.size();i++) { + if (!anExtraTables.get(i).equals("")) { + countSql.append( ", " + anExtraTables.get(i)); + selectSql.append( ", " + anExtraTables.get(i)); } } } @@ -624,31 +555,27 @@ public class Database implements StorageObject { selectSql.append(" order by ").append(anOrderByClause); } - if ((limit > -1) && (offset > -1)) { - selectSql.append(" LIMIT ").append(limit).append(" OFFSET ").append(offset); + if ((aLimit > -1) && (anOffset > -1)) { + selectSql.append(" LIMIT ").append(aLimit).append(" OFFSET ").append(anOffset); } // execute sql try { - con = getPooledCon(); - stmt = con.createStatement(); + connection = obtainConnection(); + statement = connection.createStatement(); // selecting... - rs = executeSql(stmt, selectSql.toString()); - - if (rs != null) { - if (!evaluatedMetaData) { - evalMetaData(rs.getMetaData()); - } + resultSet = executeSql(statement, selectSql.toString()); + if (resultSet != null) { theReturnList = new EntityList(); Entity theResultEntity; - while (rs.next()) { - theResultEntity = makeEntityFromResultSet(rs); + while (resultSet.next()) { + theResultEntity = makeEntityFromResultSet(resultSet); theReturnList.add(theResultEntity); offsetCount++; } - rs.close(); + resultSet.close(); } // making entitylist infos @@ -658,16 +585,16 @@ public class Database implements StorageObject { // now we decide if we have to know an overall count... count = offsetCount; - if ((limit > -1) && (offset > -1)) { - if (offsetCount == limit) { - rs = executeSql(stmt, countSql.toString()); + if ((aLimit > -1) && (anOffset > -1)) { + if (offsetCount == aLimit) { + resultSet = executeSql(statement, countSql.toString()); - if (rs != null) { - if (rs.next()) { - count = rs.getInt(1); + if (resultSet != null) { + if (resultSet.next()) { + count = resultSet.getInt(1); } - rs.close(); + resultSet.close(); } else { logger.error("Could not count: " + countSql); @@ -676,21 +603,21 @@ public class Database implements StorageObject { } theReturnList.setCount(count); - theReturnList.setOffset(offset); + theReturnList.setOffset(anOffset); theReturnList.setWhere(aWhereClause); theReturnList.setOrder(anOrderByClause); theReturnList.setStorage(this); - theReturnList.setLimit(limit); + theReturnList.setLimit(aLimit); - if (offset >= limit) { - theReturnList.setPrevBatch(offset - limit); + if (anOffset >= aLimit) { + theReturnList.setPrevBatch(anOffset - aLimit); } - if ((offset + offsetCount) < count) { - theReturnList.setNextBatch(offset + limit); + if ((anOffset + offsetCount) < count) { + theReturnList.setNextBatch(anOffset + aLimit); } - if (extraTables==null && StoreUtil.extendsStorableEntity(theEntityClass)) { + if (anExtraTables==null && StoreUtil.extendsStorableEntity(theEntityClass)) { StoreIdentifier sid = theReturnList.getStoreIdentifier(); logger.debug("CACHE (add): " + sid.toString()); o_store.add(sid); @@ -702,8 +629,8 @@ public class Database implements StorageObject { } finally { try { - if (con != null) { - freeConnection(con, stmt); + if (connection != null) { + freeConnection(connection, statement); } } catch (Throwable t) { } @@ -722,7 +649,7 @@ public class Database implements StorageObject { throws StorageObjectFailure { Map theResultHash = new HashMap(); String theResult = null; - int theType; + int type; Entity returnEntity = null; try { @@ -733,14 +660,11 @@ public class Database implements StorageObject { if (hit != null) return hit; } - - int size = metadataFields.size(); - - for (int i = 0; i < size; i++) { + for (int i = 0; i < getFieldNames().size(); i++) { // alle durchlaufen bis nix mehr da - theType = metadataTypes[i]; + type = fieldTypes[i]; - if (theType == java.sql.Types.LONGVARBINARY) { + if (type == java.sql.Types.LONGVARBINARY) { InputStreamReader is = (InputStreamReader) rs.getCharacterStream(i + 1); @@ -755,15 +679,17 @@ public class Database implements StorageObject { is.close(); theResult = theResultString.toString(); - } else { + } + else { theResult = null; } - } else { - theResult = getValueAsString(rs, (i + 1), theType); + } + else { + theResult = getValueAsString(rs, (i + 1), type); } if (theResult != null) { - theResultHash.put(metadataFields.get(i), theResult); + theResultHash.put(getFieldNames().get(i), theResult); } } @@ -805,16 +731,7 @@ public class Database implements StorageObject { * @return der Wert des Primary-keys der eingef?gten Entity */ public String insert(Entity theEntity) throws StorageObjectFailure { - //cache - invalidatePopupCache(); - - // invalidating all EntityLists corresponding with theEntityClass - if (StoreUtil.extendsStorableEntity(theEntityClass)) { - StoreContainerType stoc_type = - StoreContainerType.valueOf(theEntityClass, - StoreContainerType.STOC_TYPE_ENTITYLIST); - o_store.invalidate(stoc_type); - } + invalidateStore(); String returnId = null; Connection con = null; @@ -828,8 +745,8 @@ public class Database implements StorageObject { boolean firstField = true; // make sql-string - for (int i = 0; i < getFields().size(); i++) { - aField = (String) getFields().get(i); + for (int i = 0; i < getFieldNames().size(); i++) { + aField = (String) getFieldNames().get(i); if (!aField.equals(primaryKeyField)) { aValue = null; @@ -872,7 +789,7 @@ public class Database implements StorageObject { String sql = sqlBuf.toString(); logger.info("INSERT: " + sql); - con = getPooledCon(); + con = obtainConnection(); con.setAutoCommit(false); pstmt = con.prepareStatement(sql); @@ -920,27 +837,21 @@ public class Database implements StorageObject { * that chooses to either insert or update depending if we * have a primary key in the entity. i don't know if we * still need the streamed input fields. // rk */ + /** todo extension: check if Entity did change, otherwise we don't need * the roundtrip to the database */ /** invalidating corresponding entitylists in o_store*/ - if (StoreUtil.extendsStorableEntity(theEntityClass)) { - StoreContainerType stoc_type = - StoreContainerType.valueOf(theEntityClass, - StoreContainerType.STOC_TYPE_ENTITYLIST); - o_store.invalidate(stoc_type); - } + + invalidateStore(); String id = theEntity.getId(); String aField; StringBuffer fv = new StringBuffer(); boolean firstField = true; - //cache - invalidatePopupCache(); - // build sql statement - for (int i = 0; i < getFields().size(); i++) { - aField = (String) metadataFields.get(i); + for (int i = 0; i < getFieldNames().size(); i++) { + aField = (String) getFieldNames().get(i); // only normal cases // todo if entity.hasFieldValue returns false, then the value should be stored as null @@ -966,13 +877,13 @@ public class Database implements StorageObject { new StringBuffer("update ").append(mainTable).append(" set ").append(fv); // exceptions - if (metadataFields.contains("webdb_lastchange")) { + if (getFieldNames().contains("webdb_lastchange")) { sql.append(",webdb_lastchange=NOW()"); } // special case: the webdb_create requires the field in yyyy-mm-dd HH:mm // format so anything extra will be ignored. -mh - if (metadataFields.contains("webdb_create") && + if (getFieldNames().contains("webdb_create") && theEntity.hasFieldValue("webdb_create")) { // minimum of 10 (yyyy-mm-dd)... if (theEntity.getFieldValue("webdb_create").length() >= 10) { @@ -999,7 +910,7 @@ public class Database implements StorageObject { logger.info("UPDATE: " + sql); try { - con = getPooledCon(); + con = obtainConnection(); con.setAutoCommit(false); pstmt = con.prepareStatement(sql.toString()); @@ -1026,8 +937,6 @@ public class Database implements StorageObject { * @return boolean liefert true zurueck, wenn loeschen erfolgreich war. */ public boolean delete(String id) throws StorageObjectFailure { - invalidatePopupCache(); - // ostore send notification if (StoreUtil.extendsStorableEntity(theEntityClass)) { String uniqueId = id; @@ -1051,17 +960,21 @@ public class Database implements StorageObject { String sql = "delete from " + mainTable + " where " + primaryKeyField + "='" + id + "'"; - //theLog.printInfo("DELETE " + sql); + logger.debug("DELETE " + sql); try { - con = getPooledCon(); + con = obtainConnection(); stmt = con.createStatement(); res = stmt.executeUpdate(sql); - } catch (SQLException sqe) { + } + catch (SQLException sqe) { throwSQLException(sqe, "delete"); - } finally { + } + finally { freeConnection(con, stmt); } + invalidateStore(); + return (res > 0) ? true : false; } @@ -1073,11 +986,7 @@ public class Database implements StorageObject { * @throws StorageObjectFailure */ public int deleteByWhereClause(String aWhereClause) throws StorageObjectFailure { - invalidatePopupCache(); - if (StoreUtil.extendsStorableEntity(theEntityClass)) { - StoreContainerType stoc_type = StoreContainerType.valueOf(theEntityClass, StoreContainerType.STOC_TYPE_ENTITYLIST); - o_store.invalidate(stoc_type); - } + invalidateStore(); Statement stmt = null; Connection con = null; @@ -1087,7 +996,7 @@ public class Database implements StorageObject { //theLog.printInfo("DELETE " + sql); try { - con = getPooledCon(); + con = obtainConnection(); stmt = con.createStatement(); res = stmt.executeUpdate(sql); } @@ -1105,15 +1014,9 @@ public class Database implements StorageObject { * @return immer false */ public boolean delete(EntityList theEntityList) { - invalidatePopupCache(); - return false; } - protected void invalidatePopupCache() { - /** todo invalidates toooo much */ - } - /** * Diese Methode fuehrt den Sqlstring sql aus und timed im Logfile. * @param stmt Statemnt @@ -1157,8 +1060,8 @@ public class Database implements StorageObject { Connection connection = null; Statement statement = null; try { - List result = new Vector(); - connection = getPooledCon(); + List result = new ArrayList(); + connection = obtainConnection(); statement = connection.createStatement(); ResultSet resultset = executeSql(statement, sql); try { @@ -1224,7 +1127,7 @@ public class Database implements StorageObject { String useTable = mainTable; if (mainTablePrefix!=null && mainTablePrefix.trim().length()>0) { - useTable+=" "+mainTablePrefix; + useTable+=" "+mainTablePrefix; } StringBuffer countSql = new StringBuffer("select count(*) from ").append(useTable); @@ -1246,7 +1149,7 @@ public class Database implements StorageObject { int result = 0; try { - con = getPooledCon(); + con = obtainConnection(); stmt = con.createStatement(); ResultSet rs = executeSql(stmt, countSql.toString()); @@ -1292,7 +1195,7 @@ public class Database implements StorageObject { PreparedStatement pstmt = null; try { - con = getPooledCon(); + con = obtainConnection(); pstmt = con.prepareStatement(sql); result = pstmt.executeUpdate(); } @@ -1309,87 +1212,77 @@ public class Database implements StorageObject { } /** - * Wertet ResultSetMetaData aus und setzt interne Daten entsprechend - * @param md ResultSetMetaData + * Processes the metadata for the table this Database object is responsible for. */ - private void evalMetaData(ResultSetMetaData md) throws StorageObjectFailure { - this.evaluatedMetaData = true; - this.metadataFields = new ArrayList(); - this.metadataLabels = new ArrayList(); - this.metadataNotNullFields = new ArrayList(); + private void processMetaData(ResultSetMetaData aMetaData) throws StorageObjectFailure { + fieldNames = new ArrayList(); try { - int numFields = md.getColumnCount(); - this.metadataTypes = new int[numFields]; - - String aField; - int aType; + int numFields = aMetaData.getColumnCount(); + fieldTypes = new int[numFields]; for (int i = 1; i <= numFields; i++) { - aField = md.getColumnName(i); - metadataFields.add(aField); - metadataLabels.add(md.getColumnLabel(i)); - aType = md.getColumnType(i); - metadataTypes[i - 1] = aType; - - if (aField.equals(primaryKeyField)) { - } - - if (md.isNullable(i) == ResultSetMetaData.columnNullable) { - metadataNotNullFields.add(aField); - } + fieldNames.add(aMetaData.getColumnName(i)); + fieldTypes[i - 1] = aMetaData.getColumnType(i); } } catch (SQLException e) { - throwSQLException(e, "evalMetaData"); + throwSQLException(e, "processMetaData"); } } /** - * Wertet die Metadaten eines Resultsets fuer eine Tabelle aus, - * um die alle Columns und Typen einer Tabelle zu ermitteln. + * Retrieves metadata from the table this Database object represents */ - private void get_meta_data() throws StorageObjectFailure { - Connection con = null; - PreparedStatement pstmt = null; + private void retrieveMetaData() throws StorageObjectFailure { + Connection connection = null; + PreparedStatement statement = null; String sql = "select * from " + mainTable + " where 0=1"; try { - con = getPooledCon(); - pstmt = con.prepareStatement(sql); + connection = obtainConnection(); + statement = connection.prepareStatement(sql); logger.debug("METADATA: " + sql); - ResultSet rs = pstmt.executeQuery(); - evalMetaData(rs.getMetaData()); - rs.close(); + ResultSet resultSet = statement.executeQuery(); + try { + processMetaData(resultSet.getMetaData()); + } + finally { + resultSet.close(); + } } catch (SQLException e) { - throwSQLException(e, "get_meta_data"); + throwSQLException(e, "retrieveMetaData"); } finally { - freeConnection(con, pstmt); + freeConnection(connection, statement); } } - public Connection getPooledCon() throws StorageObjectFailure { - Connection con = null; - + public Connection obtainConnection() throws StorageObjectFailure { try { - con = SQLManager.getInstance().requestConnection(); + return MirGlobal.getDatabaseEngine().obtainConnection(); } - catch (SQLException e) { - logger.error("could not connect to the database " + e.getMessage()); - - throw new StorageObjectFailure("Could not connect to the database", e); + catch (Exception e) { + throw new StorageObjectFailure(e); } - - return con; } - public void freeConnection(Connection con, Statement stmt) - throws StorageObjectFailure { - SQLManager.closeStatement(stmt); - SQLManager.getInstance().returnConnection(con); + public void freeConnection(Connection aConnection, Statement aStatement) throws StorageObjectFailure { + try { + aStatement.close(); + } + catch (Throwable t) { + logger.warn("Can't close statemnet: " + t.toString()); + } + + try { + MirGlobal.getDatabaseEngine().releaseConnection(aConnection); + } + catch (Throwable t) { + logger.warn("Can't release connection: " + t.toString()); + } } /** @@ -1439,4 +1332,125 @@ public class Database implements StorageObject { logger.error(aMessage); throw new StorageObjectFailure(aMessage, null); } + + /** + * Invalidates any cached entity list + */ + private void invalidateStore() { + // invalidating all EntityLists corresponding with theEntityClass + if (StoreUtil.extendsStorableEntity(theEntityClass)) { + StoreContainerType stoc_type = + StoreContainerType.valueOf(theEntityClass, StoreContainerType.STOC_TYPE_ENTITYLIST); + o_store.invalidate(stoc_type); + } + } + + /** + * Retrieves a binary value + */ + public InputStream getBinaryField(String aQuery) throws StorageObjectFailure, SQLException { + Connection connection=null; + Statement statement=null; + InputStream inputStream; + InputStream imageInputStream = null; + + try { + connection = obtainConnection(); + try { + connection.setAutoCommit(false); + statement = connection.createStatement(); + ResultSet resultSet = executeSql(statement, aQuery); + + if(resultSet!=null) { + if (resultSet.next()) { + inputStream = resultSet.getBlob(1).getBinaryStream(); + imageInputStream = new BinaryFieldInputStream(inputStream, connection, statement); + } + resultSet.close(); + } + } + finally { + } + } + catch (Throwable t) { + logger.error("EntityImages.getImage failed: " + t.toString()); + t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + + try { + connection.setAutoCommit(true); + } + catch (Throwable e) { + logger.error("EntityImages.getImage resetting transaction mode failed: " + e.toString()); + e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + } + + try { + freeConnection(connection, statement); + } + catch (Throwable e) { + logger.error("EntityImages.getImage freeing connection failed: " +e.toString()); + } + + throw new StorageObjectFailure(t); + } + + return imageInputStream; + } + + /** + * Sets a binary value. The query is supposed to contain 1 ? denoting where the + * binary value should be inserted. + * + * e.g. update images set image_data = ? where id= 22 + */ + public void setBinaryField(String aQuery, byte aData[]) throws StorageObjectFailure, SQLException { + PreparedStatement statement = null; + Connection connection = obtainConnection(); + try { + connection.setAutoCommit(false); + try { + statement = connection.prepareStatement(aQuery); + statement.setBinaryStream(1, new ByteArrayInputStream(aData), aData.length); + statement.execute(); + connection.commit(); + } + finally { + connection.setAutoCommit(true); + } + } + finally { + freeConnection(connection, statement); + } + } + + /** + * a small wrapper class that allows us to store the DB connection resources + * that the BlobInputStream is using and free them upon closing of the stream + */ + private class BinaryFieldInputStream extends InputStream { + InputStream inputStream; + Connection connection; + Statement statement; + + public BinaryFieldInputStream(InputStream aBlobInputStream, Connection aConnection, Statement aStatement ) { + inputStream = aBlobInputStream; + connection = aConnection; + statement = aStatement; + } + + public void close () throws IOException { + inputStream.close(); + try { + connection.setAutoCommit(true); + freeConnection(connection, statement); + } + catch (Exception e) { + throw new IOException("close(): "+e.toString()); + } + } + + public int read() throws IOException { + return inputStream.read(); + } + } } diff --git a/source/mir/storage/StorageObject.java b/source/mir/storage/StorageObject.java index 62617e24..5f4ecc9e 100755 --- a/source/mir/storage/StorageObject.java +++ b/source/mir/storage/StorageObject.java @@ -35,6 +35,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.Map; +import java.io.InputStream; import mir.entity.Entity; import mir.entity.EntityList; @@ -65,11 +66,10 @@ public interface StorageObject { */ public int deleteByWhereClause(String aWhereClause) throws StorageObjectFailure; - public List getFields() throws StorageObjectFailure; - - public int[] getTypes() throws StorageObjectFailure; - - public List getLabels() throws StorageObjectFailure; + /** + * Returns a list of field names for this StorageObject + */ + public List getFieldNames() throws StorageObjectFailure; public void update(Entity a) throws StorageObjectFailure; @@ -81,7 +81,7 @@ public interface StorageObject { public String getTableName(); - public Connection getPooledCon() throws StorageObjectFailure; + public Connection obtainConnection() throws StorageObjectFailure; public ResultSet executeSql(Statement a, String sql) throws StorageObjectFailure, SQLException; @@ -113,4 +113,7 @@ public interface StorageObject { public int getSize(String mainTablePrefix, List extraTables, String where) throws SQLException, StorageObjectFailure; + public InputStream getBinaryField(String aQuery) throws SQLException, StorageObjectFailure; + + public void setBinaryField(String aQuery, byte aData[]) throws StorageObjectFailure, SQLException; } diff --git a/source/mir/storage/store/ObjectStore.java b/source/mir/storage/store/ObjectStore.java index f84206df..0c65b1c9 100755 --- a/source/mir/storage/store/ObjectStore.java +++ b/source/mir/storage/store/ObjectStore.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.storage.store; @@ -59,14 +59,10 @@ package mir.storage.store; * @version 1.0 */ -import java.io.BufferedInputStream; -import java.io.FileInputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.MissingResourceException; -import java.util.Properties; - import javax.servlet.http.HttpServletRequest; import mir.config.MirPropertiesConfiguration; @@ -77,28 +73,12 @@ public class ObjectStore { private final static ObjectStore INSTANCE = new ObjectStore(); private final static Map containerMap = new HashMap(); // StoreContainerType/StoreContainer private static long storeHit = 0, storeMiss = 0; - private Properties ostoreConf; + private MirPropertiesConfiguration configuration; private LoggerWrapper logger; private ObjectStore() { - String confName = null; - logger = new LoggerWrapper("Database.ObjectStore"); - Properties conf = new Properties(); - - try { - confName = - MirPropertiesConfiguration.instance().getString("Home") + - "etc/objectstore.properties"; - conf.load(new BufferedInputStream(new FileInputStream(confName))); - } - catch (java.io.FileNotFoundException fnfe) { - logger.error("could not read config file. not found: " + confName); - } - catch (Throwable t) { - logger.error("could not get config: " + t.getMessage()); - } - ostoreConf = conf; + configuration = MirPropertiesConfiguration.instance(); } public static ObjectStore getInstance() { @@ -165,14 +145,11 @@ public class ObjectStore { } /** - * Method: invalidate(StoreContainerType) - * Description: serves to invalidate a whole StoreContainer - * - * @return + * serves to invalidate a whole StoreContainer */ public void invalidate(StoreContainerType stoc_type) { if (stoc_type != null) { - /** @todo invalidates too much: + /* @todo invalidates too much: * improvement: if instanceof StoreContainerEntity && EntityList * then invalidate only StoreIdentifier matching the right table */ @@ -215,9 +192,8 @@ public class ObjectStore { public String getConfProperty(String name) { if (name != null) { - String returnValue = ""; try { - return ostoreConf.getProperty(name); + return configuration.getString(name); } catch (MissingResourceException e) { logger.error("getConfProperty: " + e.toString()); diff --git a/source/mir/storage/store/StoreUtil.java b/source/mir/storage/store/StoreUtil.java index 917ceb92..f1717e2c 100755 --- a/source/mir/storage/store/StoreUtil.java +++ b/source/mir/storage/store/StoreUtil.java @@ -78,21 +78,7 @@ public final class StoreUtil { * @return true if yes, otherwise no. */ public static final boolean extendsStorableEntity(Class aClass) { - if (aClass != null) { - if (aClass == StorableObjectEntity.class) return true; - Class superclass = aClass.getSuperclass(); - - if (superclass != null) { - if (superclass == StorableObjectEntity.class) { - return true; - } - else { - return extendsStorableEntity(superclass); - } - } - } - - return false; + return StorableObjectEntity.class.isAssignableFrom(aClass); } diff --git a/source/mir/util/CachingRewindableIterator.java b/source/mir/util/CachingRewindableIterator.java index 1edf7797..5b6b2a36 100755 --- a/source/mir/util/CachingRewindableIterator.java +++ b/source/mir/util/CachingRewindableIterator.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ package mir.util; @@ -32,6 +32,7 @@ package mir.util; import java.util.Iterator; import java.util.List; import java.util.Vector; +import java.util.ArrayList; public class CachingRewindableIterator implements RewindableIterator { private Iterator master; @@ -40,7 +41,7 @@ public class CachingRewindableIterator implements RewindableIterator { public CachingRewindableIterator(Iterator anIterator) { master = anIterator; - cachedItems = new Vector(); + cachedItems = new ArrayList(); iterationPosition = 0; } diff --git a/source/mir/util/ExceptionFunctions.java b/source/mir/util/ExceptionFunctions.java index 218213e3..d831028e 100755 --- a/source/mir/util/ExceptionFunctions.java +++ b/source/mir/util/ExceptionFunctions.java @@ -30,6 +30,9 @@ package mir.util; import java.lang.reflect.InvocationTargetException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; import multex.Failure; @@ -53,7 +56,6 @@ public class ExceptionFunctions { * Traces an exception to it's root cause, using all known exception types that support * cause exceptions. * - * @param anException * @return the cause (if found) */ @@ -76,4 +78,13 @@ public class ExceptionFunctions { return result; } + + /** + * Prints an exception's stacktrace to a String + */ + public static String getStackTrace(Throwable aThrowable) { + StringWriter writer = new StringWriter(); + aThrowable.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } } diff --git a/source/mir/util/FileFunctions.java b/source/mir/util/FileFunctions.java index bbbaa681..c9e6a109 100755 --- a/source/mir/util/FileFunctions.java +++ b/source/mir/util/FileFunctions.java @@ -29,18 +29,12 @@ */ package mir.util; -import gnu.regexp.RE; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; +import java.io.*; import java.util.Arrays; +import java.util.Collections; import java.util.List; -import java.util.Vector; + +import gnu.regexp.RE; public class FileFunctions { protected static final int FILE_COPY_BUFFER_SIZE = 65536; @@ -115,6 +109,46 @@ public class FileFunctions { } } + /** + * Copy the contents of an {@link InputStream} to a {@link File} + */ + public static void copy(InputStream aSource, File aDestination) throws IOException { + BufferedOutputStream outputStream = + new BufferedOutputStream(new FileOutputStream(aDestination), 8192); + + int read; + byte[] buf = new byte[8 * 1024]; + + while ((read = aSource.read(buf)) != -1) { + outputStream.write(buf, 0, read); + } + + aSource.close(); + outputStream.close(); + } + + /** + * Moves a {@link File} to a new location + */ + public static void move(File aSource, File aDestination) throws IOException { + aDestination.getParentFile().mkdirs(); + if (!aSource.renameTo(aDestination)) { + byte[] buffer = new byte[16384]; + FileInputStream inputStream = new FileInputStream(aSource); + FileOutputStream outputStream = new FileOutputStream(aDestination); + try { + while (inputStream.read(buffer)>0) { + outputStream.write(buffer); + } + } + finally { + outputStream.close(); + inputStream.close(); + } + aSource.delete(); + }; + } + public static class RegExpFileFilter implements FilenameFilter { private RE expression; @@ -139,16 +173,36 @@ public class FileFunctions { public boolean accept(File aDir, String aName) { return new File(aDir, aName).isDirectory(); } - } public static List getDirectoryContentsAsList(File aDirectory, FilenameFilter aFilter) { Object[] contents = aDirectory.list(aFilter); if (contents==null) - return new Vector(); + return Collections.EMPTY_LIST; else return Arrays.asList(contents); } + public static String getExtension(String aPath) { + int position = aPath.lastIndexOf('.'); + if (position>=0) { + return aPath.substring(position+1); + } + else { + return ""; + } + } + + public static boolean isAbsolutePath(String aPath) { + return new File(aPath).isAbsolute(); + } + public static File getAbsoluteOrRelativeFile(File aParentIfRelative, String aPath) { + if (isAbsolutePath(aPath)) { + return new File(aPath); + } + else { + return new File(aParentIfRelative, aPath); + } + } } \ No newline at end of file diff --git a/source/mir/util/GeneratorDateTimeFunctions.java b/source/mir/util/GeneratorDateTimeFunctions.java index e535f1a1..d7d88beb 100755 --- a/source/mir/util/GeneratorDateTimeFunctions.java +++ b/source/mir/util/GeneratorDateTimeFunctions.java @@ -42,7 +42,7 @@ public class GeneratorDateTimeFunctions { private GeneratorDateTimeFunctions() { } - public static class FormatDateFunction implements Generator.GeneratorFunction { + public static class FormatDateFunction implements Generator.Function { private String defaultTimezone; public FormatDateFunction(String aDefaultTimeZone) { @@ -96,13 +96,13 @@ public class GeneratorDateTimeFunctions { public static class DateTimeFunctions { private String defaultTimezone; - private Generator.GeneratorFunction formatDate; + private Generator.Function formatDate; public DateTimeFunctions(String aDefaultTimezone) { defaultTimezone = aDefaultTimezone; } - public Generator.GeneratorFunction getFormatDate() { + public Generator.Function getFormatDate() { if (formatDate == null) { formatDate = new FormatDateFunction(defaultTimezone); } diff --git a/source/mir/util/GeneratorFormatAdapters.java b/source/mir/util/GeneratorFormatAdapters.java index 2da18e59..becea34c 100755 --- a/source/mir/util/GeneratorFormatAdapters.java +++ b/source/mir/util/GeneratorFormatAdapters.java @@ -54,11 +54,11 @@ public class GeneratorFormatAdapters { value = aValue; } - public Generator.GeneratorFunction getFormat() { + public Generator.Function getFormat() { return new NumberFormattingFunction(); } - private class NumberFormattingFunction implements Generator.GeneratorFunction { + private class NumberFormattingFunction implements Generator.Function { public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { try { if (aParameters.size() != 1 || ! (aParameters.get(0)instanceof String)) @@ -106,7 +106,7 @@ public class GeneratorFormatAdapters { return defaultTimezone; } - public Generator.GeneratorFunction getFormat() { + public Generator.Function getFormat() { return new DateFormattingFunction(); } @@ -118,7 +118,7 @@ public class GeneratorFormatAdapters { return value; } - private class DateFormattingFunction implements Generator.GeneratorFunction { + private class DateFormattingFunction implements Generator.Function { public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { try { if (aParameters.size() < 1 || aParameters.size() > 2 || diff --git a/source/mir/util/GeneratorHTMLFunctions.java b/source/mir/util/GeneratorHTMLFunctions.java deleted file mode 100755 index bcedf17b..00000000 --- a/source/mir/util/GeneratorHTMLFunctions.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your version. - */ -package mir.util; - -import java.util.List; - -import mir.generator.Generator; -import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; - -public class GeneratorHTMLFunctions { - private GeneratorHTMLFunctions() {} - - public static class encodeURIGeneratorFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()<1 || aParameters.size()>2) - throw new GeneratorExc("encodeURIGeneratorFunction []: only 1 or 2 parameters expected"); - - if (aParameters.size()>=2) - return HTMLRoutines.encodeURL(StringRoutines.interpretAsString(aParameters.get(0)), (StringRoutines.interpretAsString(aParameters.get(1)))); - else - return HTMLRoutines.encodeURL(StringRoutines.interpretAsString(aParameters.get(0))); - - - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("encodeURIGeneratorFunction: " + t.getMessage(), t); - } - }; - } - - public static class encodeHTMLGeneratorFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("encodeHTMLGeneratorFunction: only 1 parameter expected"); - - return HTMLRoutines.encodeHTML(StringRoutines.interpretAsString(aParameters.get(0))); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("encodeHTMLGeneratorFunction: " + t.getMessage(), t); - } - }; - } - - public static class prettyEncodeHTMLGeneratorFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("prettyEncodeHTMLGeneratorFunction: only 1 parameter expected"); - - return HTMLRoutines.prettyEncodeHTML(StringRoutines.interpretAsString(aParameters.get(0))); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("prettyEncodeHTMLGeneratorFunction: " + t.getMessage(), t); - } - }; - } - - public static class encodeXMLGeneratorFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("encodeHTMLGeneratorFunction: only 1 parameter expected"); - - return HTMLRoutines.encodeXML(StringRoutines.interpretAsString(aParameters.get(0))); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("encodeHTMLGeneratorFunction: " + t.getMessage(), t); - } - }; - } -} diff --git a/source/mir/util/GeneratorIntegerFunctions.java b/source/mir/util/GeneratorIntegerFunctions.java deleted file mode 100755 index e323866e..00000000 --- a/source/mir/util/GeneratorIntegerFunctions.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your version. - */ -package mir.util; - -import java.util.List; - -import mir.generator.Generator; -import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; - -public class GeneratorIntegerFunctions { - - private GeneratorIntegerFunctions() {} - - public static class incrementFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - int incrementValue = 1; - - try { - if (aParameters.size()>2 || aParameters.size()<1) - throw new GeneratorExc("incrementFunction: 1 or 2 parameters expected: value [increment value]"); - - if (aParameters.size()>1) - incrementValue = StringRoutines.interpretAsInteger(aParameters.get(1)); - - return new Integer(StringRoutines.interpretAsInteger(aParameters.get(0)) + incrementValue); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("incrementFunction: " + t.getMessage(), t); - } - }; - } - - public static class isOddFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("isOddFunction: 1 parameters expected: value"); - - return new Boolean((StringRoutines.interpretAsInteger(aParameters.get(0)) & 1) == 1); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("isOddFunction: " + t.getMessage(), t); - } - }; - } -} \ No newline at end of file diff --git a/source/mir/util/GeneratorListFunctions.java b/source/mir/util/GeneratorListFunctions.java deleted file mode 100755 index dcb86148..00000000 --- a/source/mir/util/GeneratorListFunctions.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your version. - */ -package mir.util; - -import java.util.List; -import java.util.Vector; - -import mir.generator.Generator; -import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; - -public class GeneratorListFunctions { - private GeneratorListFunctions() {} - - public static class subListFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - int skip; - int maxSize; - - if (aParameters.size()>3 || aParameters.size()<2) - throw new GeneratorExc("iteratorSubsetFunction: 2 or 3 parameters expected"); - if (aParameters.get(0)==null) - return ""; - - if (!(aParameters.get(0) instanceof RewindableIterator) && !(aParameters.get(0) instanceof List)) - throw new GeneratorExc("iteratorSubsetFunction: first parameter must be a RewindableIterator (not a "+aParameters.get(0).getClass().getName()+")"); - - skip = StringRoutines.interpretAsInteger(aParameters.get(1)); - if (aParameters.size()>=2) - maxSize = StringRoutines.interpretAsInteger(aParameters.get(2)); - else - maxSize = -1; - - - if ((aParameters.get(0) instanceof RewindableIterator)) - return new SubsetIterator((RewindableIterator) aParameters.get(0), skip, maxSize); - else { - List list = (List) aParameters.get(0); - - if (skip>=list.size()) - return new Vector(); - if (maxSize<0 || (skip+maxSize)>=list.size()) - return list.subList(skip, list.size()); - else - return list.subList(skip, skip+maxSize); - } - } - catch (GeneratorExc e) { - throw e; - } - catch (GeneratorFailure e) { - throw e; - } - catch (Throwable e) { - throw new GeneratorFailure(e); - } - }; - } - - public static class listSizeFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("listSizeFunction: 1 parameter expected"); - if (aParameters.get(0)==null) - return ""; - - if (!(aParameters.get(0) instanceof RewindableIterator) && !(aParameters.get(0) instanceof List)) - throw new GeneratorExc("listSizeFunction: first parameter must be a RewindableIterator (not a "+aParameters.get(0).getClass().getName()+")"); - - if ((aParameters.get(0) instanceof RewindableIterator)) { - RewindableIterator iterator = (RewindableIterator) aParameters.get(0); - iterator.rewind(); - int result=0; - while (iterator.hasNext()) { - result++; - iterator.next(); - } - - iterator.rewind(); - return new Integer(result); - } - else { - List list = (List) aParameters.get(0); - return new Integer(list.size()); - } - } - catch (GeneratorExc e) { - throw e; - } - catch (GeneratorFailure e) { - throw e; - } - catch (Throwable e) { - throw new GeneratorFailure(e); - } - }; - } -} diff --git a/source/mir/util/GeneratorRegularExpressionFunctions.java b/source/mir/util/GeneratorRegularExpressionFunctions.java deleted file mode 100755 index 67d95cb9..00000000 --- a/source/mir/util/GeneratorRegularExpressionFunctions.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your version. - */ -package mir.util; - -import java.util.List; - -import mir.generator.Generator; -import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; - -public class GeneratorRegularExpressionFunctions { - - private GeneratorRegularExpressionFunctions() {} - - public static class regularExpressionReplaceFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=3) - throw new GeneratorExc("regularExpressionReplaceFunction: exactly 3 parameters expected: data, search expression, replacement"); - if (aParameters.get(0)==null) - return ""; - if (!(aParameters.get(0) instanceof String) || !(aParameters.get(1) instanceof String) || !(aParameters.get(2) instanceof String)) - throw new GeneratorExc("regularExpressionReplaceFunction: parameters must be strings"); - - return StringRoutines.performRegularExpressionReplacement((String) aParameters.get(0), (String) aParameters.get(1), (String) aParameters.get(2)); - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } - - public static class regularExpressionMatchFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=2) - throw new GeneratorExc("regularExpressionMatchFunction: exactly 2 parameters expected: data, search expression"); - if (aParameters.get(0)==null) - return new Boolean(false); - if (!(aParameters.get(0) instanceof String) || !(aParameters.get(1) instanceof String)) - throw new GeneratorExc("regularExpressionReplaceFunction: parameters must be strings"); - - return new Boolean(StringRoutines.performRegularExpressionSearch((String) aParameters.get(0), (String) aParameters.get(1))); - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } - - - -} diff --git a/source/mir/util/GeneratorStringFunctions.java b/source/mir/util/GeneratorStringFunctions.java deleted file mode 100755 index 28e4a2c7..00000000 --- a/source/mir/util/GeneratorStringFunctions.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your version. - */ -package mir.util; - -import java.util.List; - -import mir.generator.Generator; -import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; - -public class GeneratorStringFunctions { - - private GeneratorStringFunctions() {} - - public static class subStringFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()>3 || aParameters.size()<2) - throw new GeneratorExc("subStringFunction: 2 or 3 parameters expected: string from [length]"); - - if (aParameters.size()==3) { - return StringRoutines.interpretAsString(aParameters.get(0)).substring( - StringRoutines.interpretAsInteger(aParameters.get(1)), - StringRoutines.interpretAsInteger(aParameters.get(2))); - } - else { - return StringRoutines.interpretAsString(aParameters.get(0)).substring( - StringRoutines.interpretAsInteger(aParameters.get(1))); - } - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } - - public static class jdbcStringEscapeFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=1 || !(aParameters.get(0) instanceof String)) - throw new GeneratorExc("jdbcStringEscapeFunction: 1 parameter expected: string "); - - return JDBCStringRoutines.escapeStringLiteral((String) aParameters.get(0)); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } - - public static class constructStructuredStringFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("constructStructureStringFunction: 1 parameter expected: string "); - - if (aParameters.get(0)==null) - return StructuredContentParser.constructStringLiteral(""); - else - return StructuredContentParser.constructStringLiteral("" + aParameters.get(0)); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } - - public static class structuredStringParserFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=1) - throw new GeneratorExc("constructStructureStringFunction: 1 parameter expected: string "); - - if (aParameters.get(0)==null) - return null; - else - return StructuredContentParser.parse("" + aParameters.get(0)); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure(t); - } - }; - } -} \ No newline at end of file diff --git a/source/mir/util/HTTPClientHelper.java b/source/mir/util/HTTPClientHelper.java new file mode 100755 index 00000000..666f4cf7 --- /dev/null +++ b/source/mir/util/HTTPClientHelper.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ + +package mir.util; + + +import java.io.InputStream; +import java.io.IOException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.GetMethod; + +import mir.util.UtilExc; + +public class HTTPClientHelper { + private HttpClient client; + private HttpMethod method; + + public HTTPClientHelper() { + client = new HttpClient(); + client.setConnectionTimeout(5000); + client.setTimeout(5000); + } + + + public InputStream getUrl(String anUrl) throws UtilExc{ + try{ + method = new GetMethod(anUrl); + method.setFollowRedirects(true); + method.setStrictMode(false); + client.executeMethod(method); + InputStream inputStream = method.getResponseBodyAsStream(); + return inputStream; + } + catch (IOException e){ + throw new UtilExc(e.getMessage()); + } + } + + public void releaseHTTPConnection() { + method.releaseConnection(); + method.recycle(); + } + +} diff --git a/source/mir/util/HTTPParsedRequest.java b/source/mir/util/HTTPParsedRequest.java index 3ca02f11..3d9d96ff 100755 --- a/source/mir/util/HTTPParsedRequest.java +++ b/source/mir/util/HTTPParsedRequest.java @@ -29,20 +29,12 @@ */ package mir.util; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Vector; - -import javax.servlet.http.HttpServletRequest; - import mir.log.LoggerWrapper; - +import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUpload; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; public class HTTPParsedRequest { static final String MULTIPART_FORMDATA_CONTENTTYPE = "multipart/form-data"; @@ -52,23 +44,21 @@ public class HTTPParsedRequest { private int maxUploadSize; private String tempDir; - private Map stringValues; - private Map listValues; + private Map parameterStringValues; + private Map parameterListValues; private List files; - private LoggerWrapper logger; + private LoggerWrapper logger = new LoggerWrapper("Utility.HTTPParsedRequest"); public HTTPParsedRequest(HttpServletRequest aRequest, String anEncoding, int aMaxUploadSize, String aTempDir) throws UtilExc, UtilFailure { - logger = new LoggerWrapper("Utility.HTTPParsedRequest"); - request = aRequest; encoding = anEncoding; maxUploadSize = aMaxUploadSize; tempDir = aTempDir; - stringValues = new HashMap(); - listValues = new HashMap(); - files = new Vector(); + parameterStringValues = new HashMap(); + parameterListValues = new HashMap(); + files = new ArrayList(); parseRequest(aRequest); } @@ -82,7 +72,11 @@ public class HTTPParsedRequest { } public String getParameter(String aName) { - return (String) stringValues.get(aName); + return (String) parameterStringValues.get(aName); + } + + public Collection getParameterNames() { + return parameterStringValues.keySet(); } public String getHeader(String aName) { @@ -94,10 +88,10 @@ public class HTTPParsedRequest { } public List getParameterList(String aName) { - if (listValues.containsKey(aName)) - return (List) listValues.get(aName); + if (parameterListValues.containsKey(aName)) + return (List) parameterListValues.get(aName); else - return new Vector(); + return Collections.EMPTY_LIST; } protected void parseRequest(HttpServletRequest aRequest) throws UtilExc, UtilFailure { @@ -111,9 +105,9 @@ public class HTTPParsedRequest { while (e.hasMoreElements()) { String name = (String) e.nextElement(); - stringValues.put(name, aRequest.getParameter(name)); - List listValue = new Vector(Arrays.asList(aRequest.getParameterValues(name))); - listValues.put(name, listValue); + parameterStringValues.put(name, aRequest.getParameter(name)); + List listValue = new ArrayList(Arrays.asList(aRequest.getParameterValues(name))); + parameterListValues.put(name, listValue); } if (parts.size()>0 && ((String) parts.get(0)).trim().toLowerCase().equals(MULTIPART_FORMDATA_CONTENTTYPE)) { @@ -129,10 +123,11 @@ public class HTTPParsedRequest { protected void parseMultipartRequest() throws UtilExc, UtilFailure { try { - FileUpload upload = new FileUpload(); + DiskFileUpload upload = new DiskFileUpload(); + upload.setSizeThreshold(100000); upload.setSizeMax(maxUploadSize); - upload.setSizeThreshold(4096); + upload.setHeaderEncoding(encoding); upload.setRepositoryPath(tempDir); List items = upload.parseRequest(request); @@ -142,14 +137,14 @@ public class HTTPParsedRequest { FileItem item = (FileItem) i.next(); if (item.isFormField()) { - if (!stringValues.containsKey(item.getName())) { - stringValues.put(item.getFieldName(), item.getString(encoding)); + if (!parameterStringValues.containsKey(item.getName())) { + parameterStringValues.put(item.getFieldName(), item.getString(encoding)); } - List listValue = (List) listValues.get(item.getFieldName()); + List listValue = (List) parameterListValues.get(item.getFieldName()); if (listValue == null) { - listValue = new Vector(); - listValues.put(item.getFieldName(), listValue); + listValue = new ArrayList(); + parameterListValues.put(item.getFieldName(), listValue); } listValue.add(item.getString(encoding)); } diff --git a/source/mir/util/HTTPRequestParser.java b/source/mir/util/HTTPRequestParser.java index 60df2887..9b50247c 100755 --- a/source/mir/util/HTTPRequestParser.java +++ b/source/mir/util/HTTPRequestParser.java @@ -30,9 +30,8 @@ package mir.util; +import java.util.ArrayList; import java.util.List; -import java.util.Vector; - import javax.servlet.http.HttpServletRequest; public class HTTPRequestParser { @@ -79,7 +78,7 @@ public class HTTPRequestParser { public List getParameterList(String aName) { try { - List result = new Vector(); + List result = new ArrayList(); String items[] = request.getParameterValues(aName); if (items!=null) { diff --git a/source/mir/util/InternetFunctions.java b/source/mir/util/InternetFunctions.java index 2dd057b1..2260d4db 100755 --- a/source/mir/util/InternetFunctions.java +++ b/source/mir/util/InternetFunctions.java @@ -32,18 +32,19 @@ package mir.util; import java.util.List; +import java.net.InetAddress; public class InternetFunctions { private InternetFunctions() { } public static boolean isIpAddressInNetwork(String anIpAddress, String aNetwork) throws Exception { - long ipAddress = parseIPAddress(anIpAddress); + long ipAddress = parseHostNameOrIPAddress(anIpAddress); long network = 0; long netMask = (1L<<32)-1; List networkParts = StringRoutines.separateString(aNetwork, "/"); - network = parseIPAddress((String) networkParts.get(0)); + network = parseHostNameOrIPAddress((String) networkParts.get(0)); if (networkParts.size()>=2) { netMask=parseNetmask((String) networkParts.get(1)); } @@ -51,6 +52,15 @@ public class InternetFunctions { return (ipAddress & netMask ) == (network & netMask); } + public static long parseHostNameOrIPAddress(String aHostName) throws Exception { + InetAddress addr = InetAddress.getByName(aHostName.trim()); + return + ((((long) addr.getAddress()[0])&255) << 24) + + ((((long) addr.getAddress()[1])&255) << 16) + + ((((long) addr.getAddress()[2])&255) << 8) + + ((((long) addr.getAddress()[3])&255)); + } + public static long parseIPAddress(String anIpAddress) throws Exception { int[] parts = {0,0,0,0}; int i; @@ -61,7 +71,7 @@ public class InternetFunctions { try { for (i=0; i<4; i++) { - parts[i] = Integer.parseInt((String) stringParts.get(i)); + parts[i] = Integer.parseInt(((String) stringParts.get(i)).trim()); } } catch (Throwable t) { @@ -93,4 +103,5 @@ public class InternetFunctions { return (1L<<32)-1; } + } \ No newline at end of file diff --git a/source/mir/util/ParameterExpander.java b/source/mir/util/ParameterExpander.java index 769f6fb1..734bec98 100755 --- a/source/mir/util/ParameterExpander.java +++ b/source/mir/util/ParameterExpander.java @@ -42,10 +42,40 @@ import multex.Exc; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.beanutils.PropertyUtils; +/** + * Class to work with expressions. Will be gradually phased out and replaced + * with {@link mir.util.expressions.ExpressionParser} + */ public class ParameterExpander { final static String NODE_SEPARATOR = "."; final static char STRING_ESCAPE_CHARACTER = '\\'; + /** + * Fundamental method to retrieve a field of an object. Supported are + * maps, beans and objects with a generic get method + */ + public static Object getObjectField(Object anObject, Object aField) { + if (anObject instanceof Map) { + return ((Map) anObject).get(aField); + } + else if ((aField instanceof String) && PropertyUtils.isReadable(anObject, (String) aField)) { + try { + return PropertyUtils.getProperty(anObject, (String) aField); + } + catch (Throwable t) { + throw new RuntimeException(t.getMessage()); + } + } + else { + try { + return MethodUtils.invokeExactMethod(anObject, "get", aField); + } + catch (Throwable t) { + throw new RuntimeException("Invalid reference of " + aField + " into " + anObject); + } + } + } + private static Object findNode(String aKey, Map aMap, List aParts, boolean aMakeIfNotPresent) throws Exception { Iterator i; String location = ""; @@ -74,7 +104,7 @@ public class ParameterExpander { ((Map) node).put(part, newNode); } else - throw new ParameterExpanderExc( "Can't expand key {1}: {2} does not exist", new Object[]{aKey,location} ); + throw new ParameterExpanderExc( "Can't expand key " + aKey + ": " + location + " does not exist"); node = newNode; } @@ -95,7 +125,7 @@ public class ParameterExpander { Object expandedValue = findValueForKey(aMap, aKey); if (!(expandedValue instanceof String)) - throw new ParameterExpanderExc( "Value of key is not a string but a {1}", new Object[]{expandedValue.getClass().getName()} ); + throw new ParameterExpanderExc( "Value of key is not a string but a " + expandedValue.getClass().getName()); return (String) expandedValue; } @@ -108,11 +138,12 @@ public class ParameterExpander { Object node=findNode(aKey, aMap, parts, true); + // todo: bean support if (node instanceof Map) { ((Map) node).put(key, aValue); } else - throw new ParameterExpanderExc( "Can't set key {1}: not inside a Map", new Object[]{aKey} ); + throw new ParameterExpanderExc( "Can't set key " + aKey + " : not inside a Map"); } public static String expandExpression(Object aContext, String anExpression) throws Exception { @@ -143,7 +174,7 @@ public class ParameterExpander { endOfExpressionPosition++; } if (endOfExpressionPosition>=anExpression.length()) { - throw new ParameterExpanderExc("Unterminated string in {1}",new Object[]{anExpression}); + throw new ParameterExpanderExc("Unterminated string in '" +anExpression+"'"); } } endOfExpressionPosition++; @@ -153,7 +184,7 @@ public class ParameterExpander { previousPosition=endOfExpressionPosition+1; } else { - throw new ParameterExpanderExc("Missing } in {1}",new Object[]{anExpression}); + throw new ParameterExpanderExc("Missing } in " + anExpression); } } else @@ -573,28 +604,6 @@ public class ParameterExpander { return result; } - private Object evaluateObjectField(Object anObject, Object aField) { - if (anObject instanceof Map) { - return ((Map) anObject).get(aField); - } - else if ((aField instanceof String) && PropertyUtils.isReadable(anObject, (String) aField)) { - try { - return PropertyUtils.getProperty(anObject, (String) aField); - } - catch (Throwable t) { - throw new RuntimeException(t.getMessage()); - } - } - else { - try { - return MethodUtils.invokeExactMethod(anObject, "get", aField); - } - catch (Throwable t) { - throw new RuntimeException("Invalid reference of " + aField + " into " + anObject); - } - } - } - private Object parseVariable() { boolean done; Token token; @@ -612,19 +621,19 @@ public class ParameterExpander { if (!(token instanceof RightSquareBraceToken)) throw new RuntimeException("] expected"); - currentValue = evaluateObjectField(currentValue, qualifier); + currentValue = getObjectField(currentValue, qualifier); } else if (token instanceof IdentifierToken) { scanner.scan(); qualifier = ((IdentifierToken) token).getName(); - currentValue = evaluateObjectField(currentValue, qualifier); + currentValue = getObjectField(currentValue, qualifier); } else if (token instanceof LeftParenthesisToken) { - if (currentValue instanceof Generator.GeneratorFunction) { + if (currentValue instanceof Generator.Function) { parameters = parseList(); try { - currentValue = ((Generator.GeneratorFunction) currentValue).perform(parameters); + currentValue = ((Generator.Function) currentValue).perform(parameters); } catch (GeneratorExc t) { throw new RuntimeException(t.getMessage()); @@ -781,6 +790,22 @@ public class ParameterExpander { if (aValue instanceof Boolean) return ((Boolean) aValue).booleanValue(); + if (aValue instanceof RewindableIterator) { + ((RewindableIterator) aValue).rewind(); + } + + if (aValue instanceof Iterator) { + return ((Iterator) aValue).hasNext(); + } + + if (aValue instanceof List) { + return ((List) aValue).size()>0; + } + + if (aValue instanceof String) { + return ((String) aValue).length()>0; + } + return aValue!=null; } @@ -877,8 +902,8 @@ public class ParameterExpander { } public static class ParameterExpanderExc extends Exc { - public ParameterExpanderExc(String msg, Object[] objects) { - super(msg, objects); + public ParameterExpanderExc(String msg) { + super(msg); } } } \ No newline at end of file diff --git a/source/mir/util/ReflectionRoutines.java b/source/mir/util/ReflectionRoutines.java new file mode 100755 index 00000000..b15014f9 --- /dev/null +++ b/source/mir/util/ReflectionRoutines.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.util; + +import org.apache.commons.beanutils.MethodUtils; + +import java.lang.reflect.InvocationTargetException; + +public class ReflectionRoutines { + private ReflectionRoutines() { + } + + /** + * Method to overcome a shortcoming in {@link org.apache.commons.beanutils}'s + * {@link MethodUtils#invokeMethod(Object, String, Object[])} involving + * parameters that are null + */ + public static Object invokeMethod(Object aTarget, String aMethodName, Object[] aParameters) + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class parameterTypes[] = new Class[aParameters.length]; + + for (int i=0; i0) + aDestination.write(buffer, 0, amountRead); } + while (amountRead>0); + aDestination.flush(); } } diff --git a/source/mir/util/StringParseRoutines.java b/source/mir/util/StringParseRoutines.java index ee08f219..04bbc72a 100755 --- a/source/mir/util/StringParseRoutines.java +++ b/source/mir/util/StringParseRoutines.java @@ -18,13 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ @@ -32,6 +32,8 @@ package mir.util; import java.util.HashMap; import java.util.Map; +import java.util.List; +import java.util.ArrayList; public class StringParseRoutines { @@ -41,8 +43,9 @@ public class StringParseRoutines { private final static String VALUE = "[^;]*"; private final static String SEMICOLON = ";"; - // a=sdfb; c=d; e=f - + /** + * Parses an expression of the form " a = b ; c = d" into a map + */ public static Map parseValueList(String anExpression) throws SimpleParser.SimpleParserFailure, SimpleParser.SimpleParserExc { String key; String value; @@ -67,4 +70,58 @@ public class StringParseRoutines { return result; } + + /** + * Utility function for {@link #parseBracketedExpression}: + * Adds a single part of a bracketed expression by looking for a + * terminator. + */ + private static int findNextBracketedPart(String anExpression, int aStartingPosition, char anEscape, String aTerminator, List aResult) { + int position = aStartingPosition; + StringBuffer result = new StringBuffer(); + + while (position"some string {some expression} some string". + * { here starts a bracket, } ends one. + */ + public static List parseBracketedExpression(String anExpression, char anEscape, + String anOpeningBracket, String aClosingBracket) { + List result = new ArrayList(); + int position = 0; + + do { + position = findNextBracketedPart(anExpression, position, anEscape, anOpeningBracket, result); + if (position>=0) { + position+=anOpeningBracket.length(); + position = findNextBracketedPart(anExpression, position, anEscape, aClosingBracket, result); + if (position>0) { + position+=aClosingBracket.length(); + } + } + } while (position>=0); + + return result; + } } \ No newline at end of file diff --git a/source/mir/util/StringRoutines.java b/source/mir/util/StringRoutines.java index 0627dbc1..a7a41b61 100755 --- a/source/mir/util/StringRoutines.java +++ b/source/mir/util/StringRoutines.java @@ -32,7 +32,7 @@ package mir.util; import gnu.regexp.RE; import java.util.List; -import java.util.Vector; +import java.util.ArrayList; public class StringRoutines { @@ -86,12 +86,6 @@ public class StringRoutines { return result.toString(); } /** - * - * @param aText - * @param anEscapeCharacater - * @param aCharactersToReplace - * @param aStringsToSubstitute - * @return */ public static String replaceEscapedStringCharacters(String aText, char anEscapeCharacter, char[] aCharactersToReplace, String[] aStringsToSubstitute) { @@ -139,7 +133,7 @@ public class StringRoutines { return (String) aValue; if (aValue instanceof Integer) - return ((Integer) aValue).toString(); + return aValue.toString(); if (aValue == null) return ""; @@ -162,16 +156,7 @@ public class StringRoutines { throw new Exception("Integer expected, "+aValue+" found"); } - /** - * - * @param aSource - * @param aSearchExpression - * @param aReplacement - * @return - * @throws Exception - */ - public static String performRegularExpressionReplacement(String aSource, - String aSearchExpression, String aReplacement) throws UtilExc { + public static String performRegularExpressionReplacement(String aSource, String aSearchExpression, String aReplacement) { try { RE regularExpression; @@ -184,8 +169,7 @@ public class StringRoutines { } } - public static String performCaseInsensitiveRegularExpressionReplacement(String aSource, - String aSearchExpression, String aReplacement) throws UtilExc { + public static String performCaseInsensitiveRegularExpressionReplacement(String aSource, String aSearchExpression, String aReplacement) { try { RE regularExpression; @@ -198,15 +182,7 @@ public class StringRoutines { } } - /** - * - * @param aSource - * @param aSearchExpression - * @return - * @throws REException - */ - public static boolean performRegularExpressionSearch(String aSource, - String aSearchExpression) throws UtilExc { + public static boolean performRegularExpressionSearch(String aSource, String aSearchExpression) { try { RE regularExpression; @@ -230,10 +206,9 @@ public class StringRoutines { */ public static List splitString(String aString, String aSeparator) { - List result= new Vector(); + List result= new ArrayList(); int previousPosition = 0; int position; - int endOfNamePosition; if (aString!=null) { while ( (position = aString.indexOf(aSeparator, previousPosition)) >= 0) { @@ -263,7 +238,7 @@ public class StringRoutines { * @return */ public static List separateString(String aString, String aSeparator) { - List result= new Vector(); + List result= new ArrayList(); int previousPosition = 0; int position; @@ -288,13 +263,13 @@ public class StringRoutines { */ public static List splitStringWithEscape(String aString, char aSeparator, char anEscape) { - List result= new Vector(); + List result= new ArrayList(); int previousPosition = 0; int position; - int endOfNamePosition; + StringBuffer currentItem = new StringBuffer(); - if (aString!=null) { + if (aString!=null && aString.length()>0) { while ((position = indexOfCharacters(aString, new char[] {aSeparator, anEscape}, previousPosition))>=0) { currentItem.append(aString.substring(previousPosition, position)); @@ -303,11 +278,13 @@ public class StringRoutines { currentItem.delete(0, currentItem.length()); } else { - currentItem.append(aString.charAt(position)); if (aString.length()>position+1) { position=position+1; currentItem.append(aString.charAt(position)); } + else { + currentItem.append(aString.charAt(position)); + } } previousPosition = position + 1; } diff --git a/source/mir/util/StructuredContentParser.java b/source/mir/util/StructuredContentParser.java index ff32bc3a..412ecad5 100755 --- a/source/mir/util/StructuredContentParser.java +++ b/source/mir/util/StructuredContentParser.java @@ -37,7 +37,6 @@ import java.util.Vector; /** - * *

Title:

*

Description: * Class to parse structured content: @@ -58,10 +57,6 @@ import java.util.Vector; *

* Parsing is be very optimistic: no exception is ever to be thrown. *

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 */ public class StructuredContentParser { public StructuredContentParser() { @@ -133,7 +128,7 @@ public class StructuredContentParser { public char scan() { if (!isAtEnd()) { - char result =data.charAt(position); + char result = data.charAt(position); position++; return result; } @@ -196,9 +191,7 @@ public class StructuredContentParser { } public static Object parseObject(Scanner aScanner) { - Object result = null; - - aScanner.skipSpace(); + aScanner.skipSpace(); if (!aScanner.isAtEnd()) { char data = aScanner.peek(); diff --git a/source/mir/util/GeneratorExpressionFunctions.java b/source/mir/util/generator/BundleGeneratorFunction.java similarity index 56% rename from source/mir/util/GeneratorExpressionFunctions.java rename to source/mir/util/generator/BundleGeneratorFunction.java index 1cec25d4..a33a5ed2 100755 --- a/source/mir/util/GeneratorExpressionFunctions.java +++ b/source/mir/util/generator/BundleGeneratorFunction.java @@ -18,50 +18,55 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with any library licensed under the Apache Software License, - * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library - * (or with modified versions of the above that use the same license as the above), - * and distribute linked combinations including the two. You must obey the - * GNU General Public License in all respects for all of the code used other than - * the above mentioned libraries. If you modify this file, you may extend this - * exception to your version of the file, but you are not obligated to do so. + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ -package mir.util; - -import java.util.List; -import java.util.Map; +package mir.util.generator; +import mir.bundle.Bundle; import mir.generator.Generator; import mir.generator.GeneratorExc; -import mir.generator.GeneratorFailure; -public class GeneratorExpressionFunctions { - private GeneratorExpressionFunctions() { - } +import java.util.ArrayList; +import java.util.List; - public static class evaluateExpressionFunction implements Generator.GeneratorFunction { - public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { - try { - if (aParameters.size()!=2) - throw new GeneratorExc("evaluateExpressionFunction : 2 parameters expected"); +/** + * + */ +public class BundleGeneratorFunction implements Generator.Function { + private Bundle bundles[]; - Object parameter1=aParameters.get(0); + public BundleGeneratorFunction(Bundle aBundles[]) { + bundles = aBundles; + } - if (!(parameter1 instanceof Map)) - throw new GeneratorExc("evaluateExpressionFunction : first parameter must be a map"); + public Object perform(List aParameters) throws GeneratorExc { + List extraParameters = new ArrayList(aParameters); - return ParameterExpander.expandExpression((Map) parameter1, StringRoutines.interpretAsString(aParameters.get(1))); - } - catch (GeneratorExc e) { - throw e; - } - catch (Throwable t) { - throw new GeneratorFailure("encodeURIGeneratorFunction: " + t.getMessage(), t); - } - }; - } + if (aParameters.size()<1) + throw new GeneratorExc("ResourceBundleGeneratorFunction: at least 1 parameter expected"); + String key = (String) aParameters.get(0); + extraParameters.remove(0); + String message=null; + for (int j=0; jaName + * by adapting methods by the same name from the wrapped + * object. + */ + public Generator.Function get(String aName) { + return new ReflectionGeneratorFunctionAdapter(object, aName); + } +} diff --git a/source/mir/util/xml/XMLParserEngine.java b/source/mir/util/xml/XMLParserEngine.java index 5a9c0945..ee70a134 100755 --- a/source/mir/util/xml/XMLParserEngine.java +++ b/source/mir/util/xml/XMLParserEngine.java @@ -35,6 +35,9 @@ import java.io.FileInputStream; import java.io.InputStream; import java.io.StringReader; import java.io.File; +import java.io.Reader; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; @@ -97,23 +100,32 @@ public class XMLParserEngine { } /** - * - * @param anInputStream - * @param aRootHandler - * @throws mir.util.xml.XMLParserFailure - * @throws mir.util.xml.XMLParserExc + * Parse xml coming from an input stream with the system default encoding */ public void parse(String aProvider, InputStream anInputStream, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{ - parse(aProvider, new java.io.InputStreamReader(anInputStream), aRootHandler); + parse(aProvider, new InputStreamReader(anInputStream), aRootHandler); + } + + /** + * Parse xml coming from an input stream according to the given encoding + */ + public void parse(String aProvider, InputStream anInputStream, String anEncoding, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{ + try { + parse(aProvider, new InputStreamReader(anInputStream, anEncoding), aRootHandler); + } + catch (UnsupportedEncodingException e) { + throw new XMLParserExc("Unsupported encoding: " + anEncoding); + } } + /** * * @param aRootHandler * @throws mir.util.xml.XMLParserFailure * @throws mir.util.xml.XMLParserExc */ - public void parse(String aProvider, java.io.Reader aReader, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{ + public void parse(String aProvider, Reader aReader, SectionHandler aRootHandler) throws XMLParserFailure, XMLParserExc{ XMLParserProvider provider = (XMLParserProvider) providers.get(aProvider); if (provider==null) @@ -170,7 +182,7 @@ public class XMLParserEngine { } public interface XMLParserProvider { - public void parse(java.io.Reader aReader, XMLParserReceiver aReceiver) throws XMLParserExc, XMLParserFailure; + public void parse(Reader aReader, XMLParserReceiver aReceiver) throws XMLParserExc, XMLParserFailure; } private class XMLParserRunner implements XMLParserReceiver { diff --git a/source/mir/util/xml/XMLReaderTool.java b/source/mir/util/xml/XMLReaderTool.java index f9bbc52e..fb4859db 100755 --- a/source/mir/util/xml/XMLReaderTool.java +++ b/source/mir/util/xml/XMLReaderTool.java @@ -155,6 +155,7 @@ public class XMLReaderTool { return result; } + /** formats an XML name as it would look in an XML file */ public static String normalizeXMLName(mir.util.xml.XMLName aName) { String result = aName.getLocalName(); if (aName.getPrefix().length() > 0) diff --git a/source/mir/util/xml/XMLSAXParserProvider.java b/source/mir/util/xml/XMLSAXParserProvider.java index 567e0fce..0e8a8514 100755 --- a/source/mir/util/xml/XMLSAXParserProvider.java +++ b/source/mir/util/xml/XMLSAXParserProvider.java @@ -5,6 +5,7 @@ import java.util.*; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; import mir.util.ExceptionFunctions; /** @@ -44,6 +45,10 @@ class XMLSAXParserProvider implements XMLParserEngine.XMLParserProvider { throw (XMLParserFailure) t; } + if (t instanceof SAXParseException) { + throw new XMLParserExc(t.getMessage()); + } + throw new XMLParserFailure(t); } catch (Throwable t) { diff --git a/source/mir/util/xml/html/HTMLScanner.java b/source/mir/util/xml/html/HTMLScanner.java index e956ae1f..1c6ff427 100755 --- a/source/mir/util/xml/html/HTMLScanner.java +++ b/source/mir/util/xml/html/HTMLScanner.java @@ -67,6 +67,20 @@ public class HTMLScanner { (aCharacter == ':'); } + private boolean isValidUnQuotedAttributeCharacter(char aCharacter) { + int type = Character.getType(aCharacter); + + return + (type == Character.UPPERCASE_LETTER) || + (type == Character.LOWERCASE_LETTER) || + (type == Character.DECIMAL_DIGIT_NUMBER) || + (aCharacter == '.') || + (aCharacter == '#') || + (aCharacter == '-') || + (aCharacter == '_') || + (aCharacter == ':'); + } + private void skipWhiteSpace() throws IOException { while (!reader.isAtEnd() && Character.isWhitespace(reader.peek())) { reader.get(); @@ -122,7 +136,7 @@ public class HTMLScanner { reader.get(); } else { - while (!reader.isAtEnd() && isValidTagNameCharacter(reader.peek())) { + while (!reader.isAtEnd() && isValidUnQuotedAttributeCharacter(reader.peek())) { result.append(reader.get()); } } @@ -183,7 +197,11 @@ public class HTMLScanner { reader.get(); if (!reader.isAtEnd() && reader.peek()=='-') { reader.get(); - break; + if (!reader.isAtEnd() && reader.peek()=='>') { + reader.get(); + break; + } + result.append('-'); } result.append('-'); } diff --git a/source/mir/util/xml/html/HTMLSchemaInformation.java b/source/mir/util/xml/html/HTMLSchemaInformation.java index 68d21273..58562144 100755 --- a/source/mir/util/xml/html/HTMLSchemaInformation.java +++ b/source/mir/util/xml/html/HTMLSchemaInformation.java @@ -38,7 +38,8 @@ public class HTMLSchemaInformation { addInlineTag("dt"); addInlineTag("em"); addInlineTag("fieldset"); - addInlineTag("font"); + // Zapata: Removed because of frequent abuse by html writers + // addInlineTag("font"); addBlockTag("form"); addBodylessTag("frame"); addInlineTag("frameset"); diff --git a/source/mircoders/accesscontrol/AccessControl.java b/source/mircoders/accesscontrol/AccessControl.java index 42cece2f..f64a208b 100755 --- a/source/mircoders/accesscontrol/AccessControl.java +++ b/source/mircoders/accesscontrol/AccessControl.java @@ -30,14 +30,13 @@ package mircoders.accesscontrol; -import java.util.List; -import java.util.Vector; - import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; import mircoders.entity.EntityUsers; -import mircoders.module.*; -import mircoders.storage.*; +import mircoders.module.ModuleContent; + +import java.util.List; +import java.util.Vector; public class AccessControl { private UserAccessControl user; @@ -187,7 +186,7 @@ public class AccessControl { private boolean lockingOptional; public ArticleAccessControl(boolean aLockingEnabled, boolean aLockingOptional) { - contentModule = new ModuleContent(DatabaseContent.getInstance()); + contentModule = new ModuleContent(); lockingEnabled = aLockingEnabled; lockingOptional = aLockingOptional; } diff --git a/source/mircoders/entity/EntityContent.java b/source/mircoders/entity/EntityContent.java index b87ae15e..144eddca 100755 --- a/source/mircoders/entity/EntityContent.java +++ b/source/mircoders/entity/EntityContent.java @@ -45,7 +45,7 @@ import mircoders.storage.DatabaseContentToMedia; * this class implements mapping of one line of the database table content * to a java object * - * @version $Id: EntityContent.java,v 1.19.2.6 2004/02/08 21:05:02 zapata Exp $ + * @version $Id: EntityContent.java,v 1.19.2.7 2004/11/21 22:07:13 zapata Exp $ * @author mir-coders group * */ @@ -78,7 +78,7 @@ public class EntityContent extends AbstractEntity { Connection con=null;Statement stmt=null; String sql = "update content set is_produced='" + value + "' where id='" + getId()+"'"; try { - con = storageObject.getPooledCon(); + con = storageObject.obtainConnection(); /** todo should be preparedStatement: faster!! */ stmt = con.createStatement(); storageObject.executeUpdate(stmt,sql); diff --git a/source/mircoders/entity/EntityImages.java b/source/mircoders/entity/EntityImages.java index 82be8d5e..1cff9690 100755 --- a/source/mircoders/entity/EntityImages.java +++ b/source/mircoders/entity/EntityImages.java @@ -30,30 +30,20 @@ package mircoders.entity; -import java.io.File; -import java.io.IOException; +import java.io.ByteArrayOutputStream; import java.io.InputStream; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; -import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; -import mir.misc.FileUtil; import mir.storage.StorageObject; import mir.storage.StorageObjectFailure; +import mir.util.StreamCopier; import mircoders.media.ImageProcessor; -import org.postgresql.largeobject.BlobInputStream; -import org.postgresql.largeobject.LargeObject; -import org.postgresql.largeobject.LargeObjectManager; - /** * * @author RK, mh, mir-coders - * @version $Id: EntityImages.java,v 1.21.2.4 2004/01/18 17:30:58 zapata Exp $ + * @version $Id: EntityImages.java,v 1.21.2.5 2004/11/21 22:07:13 zapata Exp $ */ @@ -77,134 +67,52 @@ public class EntityImages extends EntityUploadedMedia setStorage(theStorage); } - // - // methods - - + /** + * Retrieves the image data + */ public InputStream getImage() throws StorageObjectFailure { - logger.debug("EntityImages.getimage started"); - java.sql.Connection con=null; - Statement stmt=null; - BlobInputStream in; - InputStream img_in = null; - try { - con = storageObject.getPooledCon(); - con.setAutoCommit(false); - LargeObjectManager lom; - java.sql.Connection jCon; - stmt = con.createStatement(); - ResultSet rs = storageObject.executeSql(stmt, - "select image_data from images where id="+getId()); - jCon = ((com.codestudio.sql.PoolManConnectionHandle)con) - .getNativeConnection(); - lom = ((org.postgresql.Connection)jCon).getLargeObjectAPI(); - if(rs!=null) { - if (rs.next()) { - LargeObject lob = lom.open(rs.getInt(1)); - in = (BlobInputStream)lob.getInputStream(); - img_in = new ImageInputStream(in, con, stmt); - } - rs.close(); - } + return storageObject.getBinaryField("select image_data from images where id="+getId()); } - catch (Throwable t) { - logger.error("EntityImages.getImage failed: " + t.toString()); - t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); - - try { - con.setAutoCommit(true); - } - catch (Throwable e) { - logger.error("EntityImages.getImage resetting transaction mode failed: " + e.toString()); - e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); - } - - try { - storageObject.freeConnection(con, stmt); - } - catch (Throwable e) { - logger.error("EntityImages.getImage freeing connection failed: " +e.toString()); - } - - throw new StorageObjectFailure(t); + catch (SQLException e) { + throw new StorageObjectFailure(e); } - - return img_in; } - public void setImage(InputStream in, String type) throws StorageObjectFailure { - // todo: failures should be treated in a better way: exception -> rollback instead + /** + * Processes and saves image data + */ + public void setImage(InputStream anInputStream, String type) throws StorageObjectFailure { + // todo: failures should be treated anInputStream a better way: exception -> rollback instead // of commit - if (in != null) { - - Connection con = null; - PreparedStatement pstmt = null; - File f = null; + if (anInputStream != null) { try { - logger.debug("EntityImages.settimage :: making internal representation of image"); + ByteArrayOutputStream inputData = new ByteArrayOutputStream(); + StreamCopier.copy(anInputStream, inputData); - f = File.createTempFile("mir", ".tmp", - new File(MirPropertiesConfiguration.instance().getString("TempDir"))); - FileUtil.write(f, in); - ImageProcessor processor = new ImageProcessor(f); - - con = storageObject.getPooledCon(); - con.setAutoCommit(false); - LargeObjectManager lom; - java.sql.Connection connection; - connection = ((com.codestudio.sql.PoolManConnectionHandle)con).getNativeConnection(); + ImageProcessor processor = new ImageProcessor(inputData.toByteArray()); + processor.descaleImage(maxImageSize, minDescaleRatio, minDescaleReduction); - lom = ((org.postgresql.Connection) connection).getLargeObjectAPI(); + ByteArrayOutputStream imageData = new ByteArrayOutputStream(); + processor.writeScaledData(imageData, type); + storageObject.setBinaryField("update images set image_data = ? where id = "+getId(), imageData.toByteArray()); - int oidImage = lom.create(); - LargeObject lobImage = lom.open(oidImage); - processor.descaleImage(maxImageSize, minDescaleRatio, minDescaleReduction); - processor.writeScaledData(lobImage.getOutputStream(), type); - lobImage.close(); setFieldValue("img_height", new Integer(processor.getScaledHeight()).toString()); setFieldValue("img_width", new Integer(processor.getScaledWidth()).toString()); - int oidIcon = lom.create(); - LargeObject lobIcon = lom.open(oidIcon); + imageData.reset(); processor.descaleImage(maxIconSize, minDescaleRatio, minDescaleReduction); - processor.writeScaledData(lobIcon.getOutputStream(), type); - lobIcon.close(); + processor.writeScaledData(imageData, type); + storageObject.setBinaryField("update images set icon_data = ? where id = "+getId(), imageData.toByteArray()); setFieldValue("icon_height", new Integer(processor.getScaledHeight()).toString()); setFieldValue("icon_width", new Integer(processor.getScaledWidth()).toString()); - setFieldValue("image_data", new Integer(oidImage).toString()); - setFieldValue("icon_data", new Integer(oidIcon).toString()); update(); } catch (Exception e) { throw new StorageObjectFailure(e); } - finally { - try { - if (con!=null) - con.setAutoCommit(true); - // get rid of the temp. file - } - catch (Throwable e) { - logger.error("EntityImages.setImage: unable to reset the connection to auto-commit:" + e.toString()); - } - try { - f.delete(); - } - catch (Throwable t) { - logger.error("EntityImages.setImage: unable to delete the temporary file:" + t.toString()); - } - - try { - if (con!=null) - storageObject.freeConnection(con,pstmt); - } - catch (Throwable t) { - logger.error("EntityImages.setImage: unable to free the connection:" + t.toString()); - } - } } } @@ -215,85 +123,11 @@ public class EntityImages extends EntityUploadedMedia * It will also take care of closing the OutputStream. */ public InputStream getIcon() throws StorageObjectFailure { - Connection con=null; - Statement stmt=null; - BlobInputStream in=null; - ImageInputStream img_in=null; - try { - con = storageObject.getPooledCon(); - con.setAutoCommit(false); - LargeObjectManager lom; - java.sql.Connection jCon; - stmt = con.createStatement(); - ResultSet rs = storageObject.executeSql(stmt, "select icon_data from images where id="+getId()); - jCon = ((com.codestudio.sql.PoolManConnectionHandle)con) - .getNativeConnection(); - lom = ((org.postgresql.Connection)jCon).getLargeObjectAPI(); - if(rs!=null) { - if (rs.next()) { - LargeObject lob = lom.open(rs.getInt(1)); - in = (BlobInputStream)lob.getInputStream(); - img_in = new ImageInputStream( in, con ,stmt); - //img_data = rs.getBytes(1); - } - rs.close(); - } + return storageObject.getBinaryField("select icon_data from images where id="+getId()); } - catch (Throwable t) { - logger.error("EntityImages.getIcon failed: "+t.toString()); - t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); - - try { - con.setAutoCommit(true); - } - catch (SQLException e) { - logger.error("EntityImages.getIcon resetting transaction mode failed: " + e.toString()); - e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); - } - try { - storageObject.freeConnection(con, stmt); - } - catch (Throwable e) { - logger.error("EntityImages -- freeing connection failed: " + e.getMessage()); - } - - throw new StorageObjectFailure(t); - } - - return img_in; - } - - /** - * a small wrapper class that allows us to store the DB connection resources - * that the BlobInputStream is using and free them upon closing of the stream - */ - private class ImageInputStream extends InputStream { - - InputStream _in; - Connection _con; - Statement _stmt; - - public ImageInputStream(BlobInputStream in, Connection con, - Statement stmt ) { - _in = in; - _con = con; - _stmt = stmt; - } - - public void close () throws IOException { - _in.close(); - try { - _con.setAutoCommit(true); - storageObject.freeConnection(_con,_stmt); - } - catch (Exception e) { - throw new IOException("close(): "+e.toString()); - } - } - - public int read() throws IOException { - return _in.read(); + catch (SQLException e) { + throw new StorageObjectFailure(e); } } } diff --git a/source/mircoders/entity/EntityUploadedMedia.java b/source/mircoders/entity/EntityUploadedMedia.java index 8d7c9f79..110f694f 100755 --- a/source/mircoders/entity/EntityUploadedMedia.java +++ b/source/mircoders/entity/EntityUploadedMedia.java @@ -42,7 +42,7 @@ import mircoders.storage.DatabaseUploadedMedia; /** * * @author mh, mir-coders group - * @version $Id: EntityUploadedMedia.java,v 1.26.2.7 2004/02/08 21:05:02 zapata Exp $ + * @version $Id: EntityUploadedMedia.java,v 1.26.2.8 2004/11/21 22:07:13 zapata Exp $ */ public class EntityUploadedMedia extends AbstractEntity { @@ -62,8 +62,23 @@ public class EntityUploadedMedia extends AbstractEntity { super.update(); try { - storageObject.executeUpdate( "update content set is_produced='0' where exists(select * from content_x_media where content_id=content.id and media_id=" + getId()+")"); - storageObject.executeUpdate( "update content set is_produced='0' where exists(select * from comment_x_media, comment where comment_x_media.comment_id=comment.id and comment.to_media=content.id and comment_x_media.media_id=" + getId()+")"); + storageObject.executeUpdate( + "update content " + + "set is_produced='0' " + + "from content_x_media cxm " + + "where" + + " cxm.content_id=content.id and cxm.media_id=" + getId() + ); + + storageObject.executeUpdate( + "update content " + + "set is_produced='0' " + + "from comment_x_media cxm, comment c "+ + "where " + + " cxm.comment_id = c.id and " + + " c.to_media=content.id and " + + " cxm.media_id=" + getId() + ); } catch (SQLException e) { throw new StorageObjectFailure(e); diff --git a/source/mircoders/global/Abuse.java b/source/mircoders/global/Abuse.java index 184142f0..0009749a 100755 --- a/source/mircoders/global/Abuse.java +++ b/source/mircoders/global/Abuse.java @@ -77,7 +77,7 @@ public class Abuse { private String articleBlockAction; private String commentBlockAction; private List log; - private String configFile = MirGlobal.config().getStringWithHome("Abuse.Config"); + private File configFile = MirGlobal.config().getFile("Abuse.Config"); private MirPropertiesConfiguration configuration; @@ -373,7 +373,7 @@ public class Abuse { ExtendedProperties configuration = new ExtendedProperties(); try { - configuration = new ExtendedProperties(configFile); + configuration = new ExtendedProperties(configFile.getAbsolutePath()); } catch (FileNotFoundException e) { } @@ -409,7 +409,7 @@ public class Abuse { configuration.addProperty("abuse.articleBlockAction", getArticleBlockAction()); configuration.addProperty("abuse.commentBlockAction", getCommentBlockAction()); - configuration.save(new BufferedOutputStream(new FileOutputStream(new File(configFile)),8192), "Anti abuse configuration"); + configuration.save(new BufferedOutputStream(new FileOutputStream(configFile),8192), "Anti abuse configuration"); } catch (Throwable t) { throw new RuntimeException(t.toString()); @@ -762,10 +762,16 @@ public class Abuse { } } + private String escapeConfigListEntry(String aFilterPart) { + return StringRoutines.replaceStringCharacters(aFilterPart, + new char[] {'\\', ':'}, + new String[] {"\\\\", "\\:"}); + } + private String escapeFilterPart(String aFilterPart) { return StringRoutines.replaceStringCharacters(aFilterPart, - new char[] {'\\', ':', '\n', '\r', '\t', ' '}, - new String[] {"\\\\", "\\:", "\\n", "\\r", "\\t", "\\ "}); + new char[] {'\\', '\n', '\r', '\t', ' '}, + new String[] {"\\\\", "\\n", "\\r", "\\t", "\\ "}); } private String deescapeFilterPart(String aFilterPart) { @@ -783,11 +789,11 @@ public class Abuse { FilterRule filter = (FilterRule) i.next(); String filterconfig = - escapeFilterPart(filter.getType()) + ":" + - escapeFilterPart(filter.getExpression()) + ":" + - escapeFilterPart(filter.getArticleAction()) + ":" + - escapeFilterPart(filter.getCommentAction()) + ":" + - escapeFilterPart(filter.getComments()) + ":"; + escapeConfigListEntry(escapeFilterPart(filter.getType())) + ":" + + escapeConfigListEntry(escapeFilterPart(filter.getExpression())) + ":" + + escapeConfigListEntry(escapeFilterPart(filter.getArticleAction())) + ":" + + escapeConfigListEntry(escapeFilterPart(filter.getCommentAction())) + ":" + + escapeConfigListEntry(escapeFilterPart(filter.getComments())) + ":"; if (filter.getLastHit() != null) filterconfig = filterconfig + filter.getLastHit().getTime(); diff --git a/source/mircoders/global/DatabaseEngine.java b/source/mircoders/global/DatabaseEngine.java new file mode 100755 index 00000000..32dd644b --- /dev/null +++ b/source/mircoders/global/DatabaseEngine.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.global; + +import java.sql.Connection; +import java.sql.Driver; +import java.util.Properties; + +import mir.config.MirPropertiesConfiguration; +import org.apache.commons.dbcp.ConnectionFactory; +import org.apache.commons.dbcp.DriverConnectionFactory; +import org.apache.commons.dbcp.PoolableConnection; +import org.apache.commons.dbcp.PoolableConnectionFactory; +import org.apache.commons.pool.ObjectPool; +import org.apache.commons.pool.impl.GenericObjectPool; + +public class DatabaseEngine { + private ObjectPool connectionPool; + + public DatabaseEngine() { + MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); + + Properties connectionProperties = new Properties(); + connectionProperties.put("user", configuration.getString("Database.Username")); + connectionProperties.put("password", configuration.getString("Database.Password")); + String dbHost = configuration.getString("Database.Host"); + String dbPort = configuration.getString("Database.Port"); + String dbName = configuration.getString("Database.Name"); + String dbUrl = "jdbc:postgresql://"+dbHost+":"+dbPort+"/"+dbName+"?compatible=7.1"; + String dbDriver = configuration.getString("Database.Driver"); + Driver driver; + try { + driver = (Driver) (Class.forName(dbDriver)).newInstance(); + } + catch (ClassNotFoundException e) { + throw new Error("JDBC Driver not found: " + e.toString()); + } + catch (InstantiationException e) { + throw new Error("Can't instantiate JDBC Driver: " + e.toString()); + } + catch (IllegalAccessException e) { + throw new Error("No access to JDBC Driver: " + e.toString()); + } + + connectionPool = new GenericObjectPool(null); + ConnectionFactory rawConnectionFactory = + new DriverConnectionFactory(driver, dbUrl, connectionProperties); + new PoolableConnectionFactory(rawConnectionFactory, connectionPool, + null, "select now()", false, true); + + // test the connection right before someone borrows it + ((GenericObjectPool) connectionPool).setTestOnBorrow(true); + + + } + + /** + * Obtain a database connection + */ + public Connection obtainConnection() throws Exception { + return (Connection) connectionPool.borrowObject(); + } + + /** + * release a previously obtained database connection + */ + public void releaseConnection(Connection aConnection) throws Exception { + connectionPool.returnObject(aConnection); + } + + /** + * Returns the native connection of a previously obtained connection + */ + public Connection getNativeConnection(Connection aConnection) { + return ((PoolableConnection) aConnection).getDelegate(); + } + + public String getStatus() { + return + connectionPool.getNumActive() + " / " + + (connectionPool.getNumIdle()+connectionPool.getNumActive()) + + " db conn."; + } +} diff --git a/source/mircoders/global/MRUCache.java b/source/mircoders/global/MRUCache.java index bdd6921e..f3722eb1 100755 --- a/source/mircoders/global/MRUCache.java +++ b/source/mircoders/global/MRUCache.java @@ -48,12 +48,7 @@ public class MRUCache { public MRUCache() { logger = new LoggerWrapper("Global.MRUCache"); - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new RuntimeException("Can't get configuration: " + e.getMessage()); - } + configuration = MirPropertiesConfiguration.instance(); cacheMaxItems=Integer.parseInt(configuration.getString("Global.Cache.Items")); cache = new HashMap(); mruList= new LinkedList(); diff --git a/source/mircoders/global/MirGlobal.java b/source/mircoders/global/MirGlobal.java index 4d328f8c..2306d96d 100755 --- a/source/mircoders/global/MirGlobal.java +++ b/source/mircoders/global/MirGlobal.java @@ -36,9 +36,13 @@ import java.util.List; import java.util.Map; import java.util.Vector; +import mir.bundle.BasicBundleFactory; +import mir.bundle.BundleFactory; +import mir.bundle.CascadingBundleFactory; +import mir.bundle.PropertiesFileBundleLoader; import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; import mir.entity.adapter.EntityAdapter; +import mir.log.LoggerEngine; import mir.log.LoggerWrapper; import mir.misc.ConfigException; import mircoders.accesscontrol.AccessControl; @@ -61,6 +65,14 @@ public class MirGlobal { static private Map loggedInUserIds = new HashMap(); static private LoggerWrapper logger = new LoggerWrapper("Global"); static private LoggerWrapper adminUsageLogger = new LoggerWrapper("AdminUsage"); +// static private ChangeEngine changeEngine = new ChangeEngine(); + static private DatabaseEngine databaseEngine; + + static private BundleFactory bundleFactory = + new CascadingBundleFactory( + new BasicBundleFactory( + new PropertiesFileBundleLoader( + config().getHome()))); public synchronized static MirLocalizer localizer() { String localizerClassName; @@ -73,17 +85,20 @@ public class MirGlobal { localizerClass = Class.forName(localizerClassName); } catch (Throwable t) { - throw new ConfigException("localizer class '" + localizerClassName + "' not found: " + t.toString()); + throw new ConfigException("localizer class '" + + localizerClassName + "' not found: " + t.toString()); } if (!(MirLocalizer.class.isAssignableFrom(localizerClass))) - throw new ConfigException("localizer class '" + localizerClassName + "' is not assignable from MirLocalizer"); + throw new ConfigException("localizer class '" + + localizerClassName + "' is not assignable from MirLocalizer"); try { localizer = new MirCachingLocalizerDecorator((MirLocalizer) localizerClass.newInstance()); } catch (Throwable t) { - throw new ConfigException("localizer class '" + localizerClassName + "' cannot be instantiated: " + t.toString()); + throw new ConfigException("localizer class '" + + localizerClassName + "' cannot be instantiated: " + t.toString()); } } @@ -98,7 +113,8 @@ public class MirGlobal { result.append((Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1024*1024)); result.append("M in use, "); - result.append(Thread.currentThread().activeCount()).append(" active threads"); + result.append(Thread.currentThread().activeCount()).append(" threads, "); + result.append(getDatabaseEngine().getStatus()); return result.toString(); } @@ -110,16 +126,25 @@ public class MirGlobal { return abuse; } + /** + * returns the global change engine (used to track changed files) + */ +// public static ChangeEngine getChangeEngine() { +// return changeEngine; +// } + public static MirPropertiesConfiguration config() { - try { - return MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new RuntimeException(e.getMessage()); - } + return MirPropertiesConfiguration.instance(); } - public static ProducerEngine producerEngine() { + public synchronized static DatabaseEngine getDatabaseEngine() { + if (databaseEngine==null) + databaseEngine = new DatabaseEngine(); + + return databaseEngine; + } + + public static ProducerEngine getProducerEngine() { if (producerEngine == null) { producerEngine = new ProducerEngine(); } @@ -182,13 +207,15 @@ public class MirGlobal { } } - private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getArticleOperationForName(String aName) { + private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation + getArticleOperationForName(String aName) { try { if (articleOperations == null) { articleOperations = new HashMap(); Iterator i = localizer().adminInterface().simpleArticleOperations().iterator(); while (i.hasNext()) { - MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next(); + MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = + (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next(); articleOperations.put(operation.getName(), operation); } } @@ -200,13 +227,15 @@ public class MirGlobal { } } - private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getCommentOperationForName(String aName) { + private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation + getCommentOperationForName(String aName) { try { if (commentOperations == null) { commentOperations = new HashMap(); Iterator i = localizer().adminInterface().simpleCommentOperations().iterator(); while (i.hasNext()) { - MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next(); + MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = + (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next(); commentOperations.put(operation.getName(), operation); } } @@ -243,6 +272,10 @@ public class MirGlobal { return result; } + public static BundleFactory getBundleFactory() { + return bundleFactory; + } + public static void registerLogin(String aName, String anId) { modifyLoggedInCount(aName, anId, 1); } @@ -279,6 +312,10 @@ public class MirGlobal { } } + /** + * Called whenever a modifying admin action occurs. Used to log + * the action, if admin activity logging is turned on, + */ public static void logAdminUsage(EntityUsers aUser, String anObject, String aDescription) { try { if (config().getString("Mir.Admin.LogAdminActivity", "0").equals("1")) { @@ -289,8 +326,23 @@ public class MirGlobal { } } catch (Throwable t) { - logger.error("Error while logging admin usage ("+aUser.toString()+", "+aDescription+"): " +t.toString()); + logger.error("Error while logging admin usage ("+ + aUser.toString()+", "+aDescription+"): " +t.toString()); + } + } + + /** + * Reloads all reloadable configurations, such as the producer subsystem. + */ + public static void reloadConfigurations() throws MirGlobalExc, MirGlobalFailure { + getProducerEngine().reloadConfiguration(); + try { + LoggerEngine.reload(); + } + catch (Throwable e) { + throw new MirGlobalFailure(e); } + getBundleFactory().reload(); } } diff --git a/source/mircoders/global/MirGlobalExc.java b/source/mircoders/global/MirGlobalExc.java new file mode 100755 index 00000000..0f7cd757 --- /dev/null +++ b/source/mircoders/global/MirGlobalExc.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.global; + +import multex.Exc; + +public class MirGlobalExc extends Exc { + public MirGlobalExc(String aMessage) { + super(aMessage); + } +} diff --git a/source/mircoders/global/MirGlobalFailure.java b/source/mircoders/global/MirGlobalFailure.java new file mode 100755 index 00000000..1fcdca4f --- /dev/null +++ b/source/mircoders/global/MirGlobalFailure.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.global; + +import multex.Failure; + +public class MirGlobalFailure extends Failure { + public MirGlobalFailure(Throwable aCause){ + super(aCause.getMessage(), aCause); + } + + public MirGlobalFailure(String msg, Exception cause){ + super(msg,cause); + } +} diff --git a/source/mircoders/global/ProducerEngine.java b/source/mircoders/global/ProducerEngine.java index 694fed9d..33a62675 100755 --- a/source/mircoders/global/ProducerEngine.java +++ b/source/mircoders/global/ProducerEngine.java @@ -30,6 +30,7 @@ package mircoders.global; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -43,49 +44,97 @@ import mir.producer.Producer; import mir.producer.ProducerFactory; import mir.util.GeneratorFormatAdapters; import mir.util.StringRoutines; -import multex.Exc; -import multex.Failure; -import mircoders.localizer.MirLocalizerExc; public class ProducerEngine { private JobQueue producerJobQueue; private LoggerWrapper logger; - + private Map nameToFactory; + private List factories; protected ProducerEngine() { logger = new LoggerWrapper("Producer"); producerJobQueue = new JobQueue(new LoggerWrapper("Producer.Queue")); - } - public void addJob(String aProducerFactory, String aVerb) throws ProducerEngineExc, ProducerEngineFailure { - ProducerFactory factory; + factories = new ArrayList(); + nameToFactory = new HashMap(); try { - factory = MirGlobal.localizer().producers().getFactoryForName( aProducerFactory ); + reloadConfiguration(); + } + catch (Throwable t) { + } + } + + /** + * Reloads the producer configuration + */ + public void reloadConfiguration() throws MirGlobalExc, MirGlobalFailure { + try { + factories = MirGlobal.localizer().producers().loadFactories(); + + synchronized (nameToFactory) { + nameToFactory.clear(); + + Iterator i = factories.iterator(); + while (i.hasNext()) { + ProducerFactory factory = (ProducerFactory) i.next(); + nameToFactory.put(factory.getName(), factory); + } + } + } + catch (Throwable t) { + throw new MirGlobalFailure(t); } - catch (MirLocalizerExc e) { - throw new ProducerEngineFailure(e); + } + + /** + * Looks up a producer factory by name + */ + private ProducerFactory getFactoryForName(String aName) { + synchronized (nameToFactory) { + return (ProducerFactory) nameToFactory.get(aName); } + } + + /** + * Returns all factories + */ + public List getFactories() { + return factories; + } + /** + * Adds a producer job to the queue + */ + public void addJob(String aProducerFactory, String aVerb) throws MirGlobalExc, MirGlobalFailure { + ProducerFactory factory; + + factory = getFactoryForName( aProducerFactory ); if (factory==null) - throw new ProducerEngineExc("Unknown producer: " + aProducerFactory); + throw new MirGlobalExc("Unknown producer: " + aProducerFactory); if (!factory.allowVerb(aVerb)) - throw new ProducerEngineExc("illegal producer/verb combination: " + aProducerFactory+"::"+aVerb); + throw new MirGlobalExc("illegal producer/verb combination: " + aProducerFactory+"::"+aVerb); producerJobQueue.appendJob( new ProducerJob(aProducerFactory, aVerb), aProducerFactory+"."+aVerb); } + /** + * Cancels a list of jobs by job identifier + */ public void cancelJobs(List aJobs) { producerJobQueue.cancelJobs(aJobs); }; + /** + * Cancels all jobs in the queue + */ public void cancelAllJobs() { producerJobQueue.cancelAllJobs(); }; - public void addTask(ProducerTask aTask) throws ProducerEngineExc, ProducerEngineFailure { + public void addTask(ProducerTask aTask) throws MirGlobalExc, MirGlobalFailure { addJob(aTask.getProducer(), aTask.getVerb()); } @@ -184,7 +233,7 @@ public class ProducerEngine { logger.info("Producing job: "+factoryName+"."+verb); try { - factory = MirGlobal.localizer().producers().getFactoryForName( factoryName ); + factory = getFactoryForName(factoryName); if (factory!=null) { MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap); @@ -212,22 +261,6 @@ public class ProducerEngine { } } - public static class ProducerEngineExc extends Exc { - public ProducerEngineExc(String aMessage) { - super(aMessage); - } - } - - public static class ProducerEngineFailure extends Failure { - public ProducerEngineFailure(Throwable aCause){ - super(aCause.getMessage(), aCause); - } - - public ProducerEngineFailure(String msg, Exception cause){ - super(msg,cause); - } - } - public static class ProducerTask { private String producer; private String verb; @@ -245,7 +278,7 @@ public class ProducerEngine { return producer; } - public static List parseProducerTaskList(String aList) throws ProducerEngineExc { + public static List parseProducerTaskList(String aList) throws MirGlobalExc { Iterator i; List result = new Vector(); @@ -257,7 +290,7 @@ public class ProducerEngine { List parts = StringRoutines.splitString(taskExpression, "."); if (parts.size() != 2) - throw new ProducerEngineExc("Invalid producer expression: '" + taskExpression + "'"); + throw new MirGlobalExc("Invalid producer expression: '" + taskExpression + "'"); else result.add(new ProducerEngine.ProducerTask( (String) parts.get(0), (String) parts.get(1))); } diff --git a/source/mircoders/localizer/MirAdminInterfaceLocalizer.java b/source/mircoders/localizer/MirAdminInterfaceLocalizer.java index a322cc3e..5dfaa153 100755 --- a/source/mircoders/localizer/MirAdminInterfaceLocalizer.java +++ b/source/mircoders/localizer/MirAdminInterfaceLocalizer.java @@ -29,16 +29,16 @@ */ package mircoders.localizer; +import mir.entity.adapter.EntityAdapter; +import mir.generator.Generator; + import java.util.List; import java.util.Map; -import mir.entity.adapter.EntityAdapter; - /** + * Interface to allow for localized changed to the workings of the admin system * - *

Title: Interface to allow for localized changed to the workings of the admin system

* @author Zapata - * @version 1.0 */ public interface MirAdminInterfaceLocalizer { @@ -70,17 +70,33 @@ public interface MirAdminInterfaceLocalizer { * @param aDefault The default generator * @return */ - public String getAdminPageGenerator(String aPage, Map aTemplateData, EntityAdapter aUser, String aDefault); + public String getAdminPageGenerator(String aPage, Map aTemplateData, EntityAdapter aUser, String aDefault) throws MirLocalizerExc; /** + * Prepares an article preview * - * @return + * @param aPreviewPage there may be different preview pages for a single article. + * (i.e. the same article may lead to different pages) this parameter selects one + * of those versions. See also {@link #getPreviewPages}. + * @param anArticle the article to be previewed + * @param aContext the context to be supplied to the generator + * @return the generator to be used to generate the preview + */ + public Generator prepareArticlePreview(String aPreviewPage, EntityAdapter anArticle, Map aContext) + throws MirLocalizerExc, MirLocalizerFailure; + + /** + * Return the available preview variations of one article + */ + public List getPreviewPages(EntityAdapter anArticle) throws MirLocalizerExc, MirLocalizerFailure; + + /** + * Get the {@link List} of {@link MirSimpleEntityOperation}s available for comments */ public List simpleCommentOperations(); /** - * - * @return + * Get the {@link List} of {@link MirSimpleEntityOperation}s available for articles */ public List simpleArticleOperations(); diff --git a/source/mircoders/localizer/MirAntiAbuseFilterType.java b/source/mircoders/localizer/MirAntiAbuseFilterType.java index f5a126c4..a9cf39d9 100755 --- a/source/mircoders/localizer/MirAntiAbuseFilterType.java +++ b/source/mircoders/localizer/MirAntiAbuseFilterType.java @@ -33,15 +33,7 @@ import mir.entity.Entity; import mir.session.Request; /** - * - * - *

Title: Anti-abuse filter type

- *

Description: Interface to define filter types for the anti-abuse system - *

- *

Copyright: Copyright (c) 2003

- *

Company: Mir coders

- * @author Zapata - * @version 1.0 + * Interface to define filter types for the anti-abuse system */ public interface MirAntiAbuseFilterType { diff --git a/source/mircoders/localizer/MirCachingLocalizerDecorator.java b/source/mircoders/localizer/MirCachingLocalizerDecorator.java index 7d2be0ae..e2165af9 100755 --- a/source/mircoders/localizer/MirCachingLocalizerDecorator.java +++ b/source/mircoders/localizer/MirCachingLocalizerDecorator.java @@ -126,9 +126,9 @@ public class MirCachingLocalizerDecorator implements MirLocalizer { private static class MirCachingGeneratorLocalizer implements MirGeneratorLocalizer { private MirGeneratorLocalizer master; private WriterEngine writerEngine; - private Generator.GeneratorLibrary producerGeneratorLibrary; - private Generator.GeneratorLibrary adminGeneratorLibrary; - private Generator.GeneratorLibrary openPostingGeneratorLibrary; + private Generator.Library producerGeneratorLibrary; + private Generator.Library adminGeneratorLibrary; + private Generator.Library openPostingGeneratorLibrary; public MirCachingGeneratorLocalizer(MirGeneratorLocalizer aMaster) { master = aMaster; @@ -142,7 +142,7 @@ public class MirCachingLocalizerDecorator implements MirLocalizer { return writerEngine; }; - public Generator.GeneratorLibrary makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { if (producerGeneratorLibrary==null) { producerGeneratorLibrary = master.makeProducerGeneratorLibrary(); } @@ -150,7 +150,7 @@ public class MirCachingLocalizerDecorator implements MirLocalizer { return producerGeneratorLibrary; }; - public Generator.GeneratorLibrary makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { if (adminGeneratorLibrary==null) { adminGeneratorLibrary = master.makeAdminGeneratorLibrary(); } @@ -158,7 +158,7 @@ public class MirCachingLocalizerDecorator implements MirLocalizer { return adminGeneratorLibrary; }; - public Generator.GeneratorLibrary makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { if (openPostingGeneratorLibrary==null) { openPostingGeneratorLibrary = master.makeOpenPostingGeneratorLibrary(); } diff --git a/source/mircoders/localizer/MirGeneratorLocalizer.java b/source/mircoders/localizer/MirGeneratorLocalizer.java index 583391e5..2065c2ac 100755 --- a/source/mircoders/localizer/MirGeneratorLocalizer.java +++ b/source/mircoders/localizer/MirGeneratorLocalizer.java @@ -36,7 +36,7 @@ import mir.generator.WriterEngine; public interface MirGeneratorLocalizer { public WriterEngine makeWriterEngine() throws MirLocalizerExc, MirLocalizerFailure; - public Generator.GeneratorLibrary makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; - public Generator.GeneratorLibrary makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; - public Generator.GeneratorLibrary makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; + public Generator.Library makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; + public Generator.Library makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; + public Generator.Library makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure; } \ No newline at end of file diff --git a/source/mircoders/localizer/MirOpenPostingLocalizer.java b/source/mircoders/localizer/MirOpenPostingLocalizer.java index c8830b36..fccebe34 100755 --- a/source/mircoders/localizer/MirOpenPostingLocalizer.java +++ b/source/mircoders/localizer/MirOpenPostingLocalizer.java @@ -40,49 +40,23 @@ import mircoders.entity.EntityContent; public interface MirOpenPostingLocalizer { /** - * Class to encapsulate a validation error * - *

Title:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 - */ - - /** - * - * @param aRequest - * @param aSession - * @return - * @throws MirLocalizerExc - * @throws MirLocalizerFailure */ public SessionHandler getOpenSessionHandler(Request aRequest, Session aSession) throws MirLocalizerExc, MirLocalizerFailure; /** - * - * @param aComment - * @throws MirLocalizerExc - * @throws MirLocalizerFailure + * This method will be called after a comment has been posted + * via the open posting interface. */ public void afterCommentPosting(EntityComment aComment) throws MirLocalizerExc, MirLocalizerFailure; /** * This method will be called after an article is posted via the open posting interface. - * - * @param aContent - * @throws MirLocalizerExc - * @throws MirLocalizerFailure */ public void afterContentPosting(EntityContent aContent) throws MirLocalizerExc, MirLocalizerFailure; /** * - * - * @return - * @throws MirLocalizerExc - * @throws MirLocalizerFailure */ public List getAntiAbuseFilterTypes() throws MirLocalizerExc, MirLocalizerFailure; diff --git a/source/mircoders/localizer/MirProducerLocalizer.java b/source/mircoders/localizer/MirProducerLocalizer.java index b389f8fe..25e600d7 100755 --- a/source/mircoders/localizer/MirProducerLocalizer.java +++ b/source/mircoders/localizer/MirProducerLocalizer.java @@ -31,11 +31,12 @@ package mircoders.localizer; import java.util.List; -import mir.producer.ProducerFactory; - public interface MirProducerLocalizer { - public List factories() throws MirLocalizerExc, MirLocalizerFailure; - public ProducerFactory getFactoryForName(String aName); + /** + * Loads the factories. Should return a list of implementations of + * {@link mir.producer.ProducerFactory} + */ + public List loadFactories() throws MirLocalizerExc, MirLocalizerFailure; public List getRecipeNames() throws MirLocalizerExc, MirLocalizerFailure; public void produceRecipe(String aName) throws MirLocalizerExc, MirLocalizerFailure; diff --git a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java index 224d980a..b4a50df2 100755 --- a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java @@ -30,46 +30,75 @@ package mircoders.localizer.basic; -import java.util.Arrays; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - +import mir.bundle.Bundle; +import mir.config.MirPropertiesConfiguration; import mir.entity.Entity; import mir.entity.adapter.EntityAdapter; +import mir.entity.adapter.EntityAdapterExc; +import mir.generator.Generator; +import mir.generator.GeneratorExc; import mir.log.LoggerWrapper; import mir.misc.StringUtil; +import mir.module.ModuleExc; import mir.storage.StorageObjectFailure; import mir.util.DateTimeFunctions; import mir.util.EntityUtility; +import mir.util.StringRoutines; +import mir.util.generator.BundleGeneratorFunction; import mircoders.entity.EntityComment; import mircoders.entity.EntityContent; import mircoders.global.MirGlobal; import mircoders.localizer.MirAdminInterfaceLocalizer; import mircoders.localizer.MirLocalizerExc; import mircoders.localizer.MirLocalizerFailure; +import mircoders.module.ModuleLanguage; import mircoders.storage.DatabaseContent; +import java.util.*; + public class MirBasicAdminInterfaceLocalizer implements MirAdminInterfaceLocalizer { - private Vector simpleCommentOperations; - private Vector simpleArticleOperations; + /** preview page name (String) -> generator name (String) */ + private Map previewPages; + private List previewPageNames; + + private List simpleCommentOperations; + private List simpleArticleOperations; private Map simpleCommentOperationsMap; private Map simpleArticleOperationsMap; + protected static LoggerWrapper logger = new LoggerWrapper("Localizer.AdminInterface");; + protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); - public MirBasicAdminInterfaceLocalizer() throws MirLocalizerFailure, MirLocalizerExc { + public MirBasicAdminInterfaceLocalizer() throws MirLocalizerFailure { - simpleCommentOperations = new Vector(); - simpleArticleOperations = new Vector(); + simpleCommentOperations = new ArrayList(); + simpleArticleOperations = new ArrayList(); simpleCommentOperationsMap = new HashMap(); simpleArticleOperationsMap = new HashMap(); + previewPages = new HashMap(); + previewPageNames = new ArrayList(); + + String[] previewConfiguration = configuration.getStringArray("Mir.Localizer.Admin.ArticlePreview"); + + for (int i = 0; iTitle:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 + * Wrapper around a collection of common filter classes for Mir's + * anti-abuse filtering system. */ - public class MirBasicAntiAbuseFilterTypes { + protected static final LoggerWrapper logger = new LoggerWrapper("Localizer.ProducerAssistant"); + private MirBasicAntiAbuseFilterTypes() { } @@ -69,20 +66,18 @@ public class MirBasicAntiAbuseFilterTypes { /** * A basic ip filter. Supports x.x.x.x, x.x.x.x/x and x.x.x.x/x.x.x.x expressions. - * - *

Title:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 */ - public static class IPFilter extends BasicFilterType { + /** + * + */ public IPFilter(String aName) { super(aName); } + /** + * + */ public boolean validate(String anExpression) { try { InternetFunctions.isIpAddressInNetwork("1.1.1.1", anExpression); @@ -93,6 +88,9 @@ public class MirBasicAntiAbuseFilterTypes { } }; + /** + * + */ public boolean test(String anExpression, Entity anEntity, Request aRequest) { try { return InternetFunctions.isIpAddressInNetwork(aRequest.getHeader("ip"), anExpression); @@ -105,15 +103,7 @@ public class MirBasicAntiAbuseFilterTypes { /** * A regular expression filter. - * - *

Title:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 */ - public static class RegularExpressionFilter extends BasicFilterType { private boolean exactMatch; private boolean caseSensitive; @@ -159,11 +149,11 @@ public class MirBasicAntiAbuseFilterTypes { Iterator j; int flags = 0; - if (caseSensitive) - // TODO jlint says this operator is useless + if (!caseSensitive) { flags |= RE.REG_ICASE; + } - RE regularExpression = new RE(anExpression, RE.REG_ICASE); + RE regularExpression = new RE(anExpression, flags); switch (fieldKind) { case REQUEST_HEADERS: @@ -171,7 +161,8 @@ public class MirBasicAntiAbuseFilterTypes { j = selectedFields.iterator(); while (j.hasNext()) { - String field = aRequest.getHeader( (String) j.next()); + String fieldName = (String) j.next(); + String field = aRequest.getHeader(fieldName); if (exactMatch) { if (field != null && regularExpression.isMatch(field)) { diff --git a/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java b/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java index dac7f834..8f5ac499 100755 --- a/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java +++ b/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java @@ -30,50 +30,35 @@ package mircoders.localizer.basic; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - import mir.entity.Entity; import mir.misc.StringUtil; -import mir.session.Request; -import mir.session.Response; -import mir.session.Session; -import mir.session.SessionExc; -import mir.session.SessionFailure; -import mir.session.UploadedFile; -import mir.session.ValidationHelper; +import mir.session.*; +import mir.util.EntityUtility; import mircoders.entity.EntityContent; import mircoders.global.MirGlobal; import mircoders.media.MediaUploadProcessor; import mircoders.module.ModuleArticleType; import mircoders.module.ModuleContent; import mircoders.module.ModuleMediafolder; -import mircoders.storage.DatabaseArticleType; -import mircoders.storage.DatabaseContent; -import mircoders.storage.DatabaseContentToMedia; -import mircoders.storage.DatabaseContentToTopics; -import mircoders.storage.DatabaseMediafolder; +import mircoders.storage.*; + +import java.util.*; /** - * - *

Title: Experimental session handler for article postings

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author Zapata - * @version 1.0 + * Extensible handler for open article postings */ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler { - protected ModuleContent contentModule = new ModuleContent(DatabaseContent.getInstance()); + protected ModuleContent contentModule = new ModuleContent(); protected DatabaseContentToMedia contentToMedia = DatabaseContentToMedia.getInstance(); protected DatabaseContent contentDatabase = DatabaseContent.getInstance(); public MirBasicArticlePostingHandler() { - super(); + this(false); + } + + public MirBasicArticlePostingHandler(boolean aPersistentUploadedFiles) { + super(aPersistentUploadedFiles); setResponseGenerators( configuration.getString("Localizer.OpenSession.article.EditTemplate"), @@ -81,11 +66,13 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler configuration.getString("Localizer.OpenSession.article.UnsupportedMediaTemplate"), configuration.getString("Localizer.OpenSession.article.DoneTemplate")); } - + /** + * {@inheritDoc} + */ protected void initializeResponseData(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { super.initializeResponseData(aRequest, aSession, aResponse); - Iterator i = DatabaseContent.getInstance().getFields().iterator(); + Iterator i = DatabaseContent.getInstance().getFieldNames().iterator(); while (i.hasNext()) { String field = (String) i.next(); aResponse.setResponseValue(field, aRequest.getParameter(field)); @@ -93,6 +80,9 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler aResponse.setResponseValue("to_topic", aRequest.getParameters("to_topic")); } + /** + * {@inheritDoc} + */ public void validate(List aResults, Request aRequest, Session aSession) throws SessionExc, SessionFailure { super.validate(aResults, aRequest, aSession); @@ -102,6 +92,10 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler ValidationHelper.testFieldEntered(aRequest, "content_data", "validationerror.missing", aResults); } + /** + * Called just before the article is stored in the database. + * The last opportunity to alter fields. + */ public void finalizeArticle(Request aRequest, Session aSession, EntityContent anArticle) throws SessionExc, SessionFailure { try { anArticle.setFieldValue("is_published", "1"); @@ -110,7 +104,7 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler anArticle.setFieldValue("is_html", "0"); anArticle.setFieldValue("publish_path", StringUtil.webdbDate2path(anArticle. getFieldValue("date"))); - ModuleArticleType module = new ModuleArticleType(DatabaseArticleType.getInstance()); + ModuleArticleType module = new ModuleArticleType(); anArticle.setFieldValue("to_article_type", module.articleTypeIdForName(configuration.getString("Localizer.OpenSession.article.DefaultArticleType"))); anArticle.setFieldValue("to_publisher", "1"); } @@ -119,12 +113,16 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler } } - public void setArticleTopics(Request aRequest, Session aSession, EntityContent aContent) throws SessionExc, SessionFailure { + /** + * Extracts topics from the request and associated the + * article to them. + */ + public void setArticleTopics(Request aRequest, Session aSession, EntityContent anArticle) throws SessionExc, SessionFailure { // topics: List topics = aRequest.getParameters("to_topic"); if (topics.size() > 0) { try { - DatabaseContentToTopics.getInstance().setTopics(aContent.getId(), topics); + DatabaseContentToTopics.getInstance().setTopics(anArticle.getId(), topics); } catch (Throwable e) { logger.error("setting content_x_topic failed"); @@ -149,24 +147,29 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler } aSession.setAttribute("content", article); - setArticleTopics(aRequest, aSession, article); - } catch (Throwable t) { throw new SessionFailure(t); } } - public void processUploadedFile(Request aRequest, Session aSession, UploadedFile aFile) throws SessionExc, SessionFailure { + public void processAttachmentError(Request aRequest, Session aSession, Attachment aFile, Throwable anError) { + EntityUtility.appendLineToField( ((EntityContent) aSession.getAttribute("content")), "comment", + "error with attachment: " + anError.toString()); + ((EntityContent) aSession.getAttribute("content")).update(); + } + + public void processAttachment(Request aRequest, Session aSession, Attachment aFile) throws SessionExc, SessionFailure { try { Map values = new HashMap(); - values.put("title", aRequest.getParameter(aFile.getFieldName()+"_title")); + values.put("creator", aRequest.getParameter("creator")); + values.putAll(aFile.getAllAttributes()); values.put("creator", aRequest.getParameter("creator")); values.put("to_publisher", "0"); values.put("is_published", "1"); values.put("is_produced", "1"); - ModuleMediafolder module = new ModuleMediafolder(DatabaseMediafolder.getInstance()); + ModuleMediafolder module = new ModuleMediafolder(); values.put("to_media_folder", module.mediaFolderIdForName(configuration.getString("Localizer.OpenSession.article.DefaultMediaFolder"))); Entity mediaItem = MediaUploadProcessor.processMediaUpload(aFile, values); diff --git a/source/mircoders/localizer/basic/MirBasicChildArticlePostingHandler.java b/source/mircoders/localizer/basic/MirBasicChildArticlePostingHandler.java index 8e4cdcbc..f8c49fea 100755 --- a/source/mircoders/localizer/basic/MirBasicChildArticlePostingHandler.java +++ b/source/mircoders/localizer/basic/MirBasicChildArticlePostingHandler.java @@ -36,7 +36,10 @@ import mir.session.SessionExc; import mir.session.SessionFailure; import mircoders.entity.EntityContent; - +/** + * Handler for open postings of "child articles", that is articles + * linked to other articles. Used frequently for translations. + */ public class MirBasicChildArticlePostingHandler extends MirBasicArticlePostingHandler { public MirBasicChildArticlePostingHandler() { super(); @@ -44,12 +47,25 @@ public class MirBasicChildArticlePostingHandler extends MirBasicArticlePostingHa setNormalResponseGenerator(configuration.getString("Localizer.OpenSession.article.EditTemplate")); } + /** + * {@inheritDoc} + * + *

+ * This class overrides this method to set the parent article. + */ public void finalizeArticle(Request aRequest, Session aSession, EntityContent anArticle) throws SessionExc, SessionFailure { super.finalizeArticle(aRequest, aSession, anArticle); anArticle.setFieldValue("to_content", (String) aSession.getAttribute("to_content")); } + /** + * {@inheritDoc} + * + *

+ * Overridden by this class to retrieve and store the to be associated + * parent article for subsequent usage. + */ protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure { super.initializeSession(aRequest, aSession); diff --git a/source/mircoders/localizer/basic/MirBasicCommentPostingHandler.java b/source/mircoders/localizer/basic/MirBasicCommentPostingHandler.java index 3e6e6a3a..3661b974 100755 --- a/source/mircoders/localizer/basic/MirBasicCommentPostingHandler.java +++ b/source/mircoders/localizer/basic/MirBasicCommentPostingHandler.java @@ -29,30 +29,22 @@ */ package mircoders.localizer.basic; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - import mir.entity.Entity; -import mir.session.Request; -import mir.session.Response; -import mir.session.Session; -import mir.session.SessionExc; -import mir.session.SessionFailure; -import mir.session.UploadedFile; -import mir.session.ValidationHelper; +import mir.session.*; +import mir.util.EntityUtility; import mircoders.entity.EntityComment; +import mircoders.entity.EntityContent; import mircoders.global.MirGlobal; import mircoders.media.MediaUploadProcessor; import mircoders.module.ModuleComment; import mircoders.module.ModuleCommentStatus; import mircoders.module.ModuleMediafolder; -import mircoders.storage.DatabaseComment; -import mircoders.storage.DatabaseCommentStatus; -import mircoders.storage.DatabaseCommentToMedia; -import mircoders.storage.DatabaseContent; -import mircoders.storage.DatabaseMediafolder; +import mircoders.storage.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * @@ -65,12 +57,17 @@ import mircoders.storage.DatabaseMediafolder; */ public class MirBasicCommentPostingHandler extends MirBasicPostingSessionHandler { - protected ModuleComment commentModule = new ModuleComment(DatabaseComment.getInstance()); + protected ModuleComment commentModule = new ModuleComment(); protected DatabaseCommentToMedia commentToMedia = DatabaseCommentToMedia.getInstance(); public MirBasicCommentPostingHandler() { - super(); + this(false); + } + + + public MirBasicCommentPostingHandler(boolean aPersistentUploadedFiles) { + super(aPersistentUploadedFiles); setResponseGenerators( configuration.getString("Localizer.OpenSession.comment.EditTemplate"), @@ -82,7 +79,7 @@ public class MirBasicCommentPostingHandler extends MirBasicPostingSessionHandler protected void initializeResponseData(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { super.initializeResponseData(aRequest, aSession, aResponse); - Iterator i = DatabaseComment.getInstance().getFields().iterator(); + Iterator i = DatabaseComment.getInstance().getFieldNames().iterator(); while (i.hasNext()) { String field = (String) i.next(); aResponse.setResponseValue(field, aRequest.getParameter(field)); @@ -110,7 +107,7 @@ public class MirBasicCommentPostingHandler extends MirBasicPostingSessionHandler public void finalizeComment(Request aRequest, Session aSession, EntityComment aComment) throws SessionExc, SessionFailure { try { aComment.setFieldValue("is_published", "1"); - ModuleCommentStatus module = new ModuleCommentStatus(DatabaseCommentStatus.getInstance()); + ModuleCommentStatus module = new ModuleCommentStatus(); aComment.setFieldValue("to_comment_status", module.commentStatusIdForName(configuration.getString("Localizer.OpenSession.comment.DefaultCommentStatus"))); aComment.setFieldValue("is_html", "0"); aComment.setFieldValue("to_media", (String) aSession.getAttribute("to_media")); @@ -140,14 +137,14 @@ public class MirBasicCommentPostingHandler extends MirBasicPostingSessionHandler } } - public void processUploadedFile(Request aRequest, Session aSession, UploadedFile aFile) throws SessionExc, SessionFailure { + public void processAttachment(Request aRequest, Session aSession, Attachment aFile) throws SessionExc, SessionFailure { try { Map values = new HashMap(); - values.put("title", aRequest.getParameter(aFile.getFieldName()+"_title")); values.put("creator", aRequest.getParameter("creator")); + values.putAll(aFile.getAllAttributes()); values.put("to_publisher", "0"); values.put("is_published", "1"); - ModuleMediafolder module = new ModuleMediafolder(DatabaseMediafolder.getInstance()); + ModuleMediafolder module = new ModuleMediafolder(); values.put("to_media_folder", module.mediaFolderIdForName(configuration.getString("Localizer.OpenSession.comment.DefaultMediaFolder"))); Entity mediaItem = MediaUploadProcessor.processMediaUpload(aFile, values); @@ -159,6 +156,13 @@ public class MirBasicCommentPostingHandler extends MirBasicPostingSessionHandler } } + public void processAttachmentError(Request aRequest, Session aSession, Attachment aFile, Throwable anError) { + EntityUtility.appendLineToField( ((EntityComment) aSession.getAttribute("comment")), "comment", + "error with attachment: " + anError.toString()); + + ((EntityComment) aSession.getAttribute("comment")).update(); + } + public void postProcessRequest(Request aRequest, Session aSession) throws SessionExc, SessionFailure { EntityComment comment = (EntityComment) aSession.getAttribute("comment"); diff --git a/source/mircoders/localizer/basic/MirBasicDataModelLocalizer.java b/source/mircoders/localizer/basic/MirBasicDataModelLocalizer.java index 25d85e08..4a41049f 100755 --- a/source/mircoders/localizer/basic/MirBasicDataModelLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicDataModelLocalizer.java @@ -29,20 +29,18 @@ */ package mircoders.localizer.basic; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Vector; - import mir.config.MirPropertiesConfiguration; import mir.entity.Entity; import mir.entity.adapter.EntityAdapter; import mir.entity.adapter.EntityAdapterDefinition; import mir.entity.adapter.EntityAdapterModel; +import mir.generator.Generator; +import mir.generator.GeneratorExc; +import mir.generator.GeneratorFailure; import mir.log.LoggerWrapper; import mir.media.MediaHandler; import mir.misc.NumberUtils; +import mir.util.JDBCStringRoutines; import mir.util.ParameterExpander; import mir.util.RewindableIterator; import mir.util.StructuredContentParser; @@ -54,40 +52,16 @@ import mircoders.localizer.MirLocalizerExc; import mircoders.localizer.MirLocalizerFailure; import mircoders.media.MediaHelper; import mircoders.module.ModuleContent; -import mircoders.storage.DatabaseArticleType; -import mircoders.storage.DatabaseAudio; -import mircoders.storage.DatabaseBreaking; -import mircoders.storage.DatabaseComment; -import mircoders.storage.DatabaseCommentStatus; -import mircoders.storage.DatabaseContent; -import mircoders.storage.DatabaseContentToMedia; -import mircoders.storage.DatabaseContentToTopics; -import mircoders.storage.DatabaseImageType; -import mircoders.storage.DatabaseImages; -import mircoders.storage.DatabaseLanguage; -import mircoders.storage.DatabaseMediaType; -import mircoders.storage.DatabaseMediafolder; -import mircoders.storage.DatabaseMessages; -import mircoders.storage.DatabaseOther; -import mircoders.storage.DatabaseTopics; -import mircoders.storage.DatabaseUploadedMedia; -import mircoders.storage.DatabaseUsers; -import mircoders.storage.DatabaseVideo; - -public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { - protected LoggerWrapper logger; - protected MirPropertiesConfiguration configuration; +import mircoders.module.ModuleLanguage; +import mircoders.storage.*; +import multex.Failure; - public MirBasicDataModelLocalizer() throws MirLocalizerFailure, MirLocalizerExc { - logger = new LoggerWrapper("Localizer.DataModel"); +import java.util.*; - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (Throwable e) { - throw new MirLocalizerFailure("Can't get configuration: " + e.getMessage(), e); - } - } +public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { + protected LoggerWrapper logger = new LoggerWrapper("Localizer.DataModel"); + protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); + protected ModuleLanguage languageModule = new ModuleLanguage(); protected void constructContentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure, MirLocalizerExc { try { @@ -139,12 +113,32 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { anEntityAdapterDefinition.addCalculatedField("operations", new EntityToSimpleOperationsField(MirGlobal.localizer().adminInterface().simpleArticleOperations())); + + anEntityAdapterDefinition.addCalculatedField("languagename", new ContentToLanguageNameField()); + + anEntityAdapterDefinition.addCalculatedField("is_original", new ContentIsOriginalField()); + anEntityAdapterDefinition.addCalculatedField("to_original", new ContentToOriginalField()); + anEntityAdapterDefinition.addCalculatedField("to_translations", new ContentToTranslationsField()); + anEntityAdapterDefinition.addCalculatedField("to_translation", new ContentToTranslationField()); + + anEntityAdapterDefinition.addCalculatedField("previews", new EntityAdapterDefinition.CalculatedField() { + public Object getValue(EntityAdapter anEntityAdapter) { + try { + return MirGlobal.localizer().adminInterface().getPreviewPages(anEntityAdapter); + } + catch (MirLocalizerExc e) { + throw new Failure("Cannot get previews for article", e); + } + } + }); } catch (Throwable t) { throw new MirLocalizerFailure(t.getMessage(), t); } } + + protected void constructCommentAdapterDefinition(EntityAdapterDefinition anEntityAdapterDefinition) throws MirLocalizerFailure { try { anEntityAdapterDefinition.addDBDateField("creationdate", "webdb_create", configuration.getString("Mir.DefaultTimezone")); @@ -228,6 +222,7 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { definition.addCalculatedField("info", new MediaToMediaInfoField()); definition.addCalculatedField("big_icon", new MediaToBigIconField()); result.addMapping( "video", DatabaseVideo.getInstance(), definition); + definition = new EntityAdapterDefinition(); definition.addCalculatedField("mediafolder", new MediaToMediaFolderField()); definition.addCalculatedField("human_readable_size", new HumanReadableSizeField("value")); @@ -249,8 +244,6 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { definition.addCalculatedField("structuredProfile", new StructuredContentField("profile")); result.addMapping( "user", DatabaseUsers.getInstance(), definition); - result.addMapping( "otherMedia", DatabaseOther.getInstance(), new EntityAdapterDefinition()); - result.addMapping( "content_x_topic", DatabaseContentToTopics.getInstance(), new EntityAdapterDefinition()); } @@ -807,7 +800,7 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { private ModuleContent contentModule; public ContentToIsLockedField() { - contentModule = new ModuleContent(DatabaseContent.getInstance()); + contentModule = new ModuleContent(); } public Object getValue(EntityAdapter anEntityAdapter) { @@ -819,4 +812,119 @@ public class MirBasicDataModelLocalizer implements MirDataModelLocalizer { } } } + protected class ContentIsOriginalField implements EntityAdapterDefinition.CalculatedField { + public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure { + try { + + //ML: add check on article type + boolean result = (anEntityAdapter.get("parent")==null); + + return new Boolean(result); + } + catch (Throwable t) { + throw new MirLocalizerFailure(t); + } + } + } + + protected class ContentToOriginalField implements EntityAdapterDefinition.CalculatedField { + public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure { + try { + if (anEntityAdapter.get("parent")!=null) + return anEntityAdapter.get("parent"); + else + return anEntityAdapter; + } + catch (Throwable t) { + throw new MirLocalizerFailure(t); + } + } + } + + protected class ContentToTranslationsField implements EntityAdapterDefinition.CalculatedField { + public Object getValue(EntityAdapter anEntityAdapter) { + try { + return anEntityAdapter.getRelation( + "is_published='t' and to_content="+anEntityAdapter.get("id"), + "id", + "content" ); + } + catch (Throwable t) { + throw new RuntimeException(t.getMessage()); + } + } + } + + protected class ContentToLanguageNameField implements EntityAdapterDefinition.CalculatedField { + public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure { + try { + String result = ""; + EntityAdapter language = (EntityAdapter) anEntityAdapter.get("language"); + if (language != null) { + if (language.get("code").equals("ot")) { + result = ((String) anEntityAdapter.get("subtitle")).trim(); + if (result == null || result.equals("")) + result = (String) language.get("name"); + } else { + result = (String) language.get("name"); + } + } + + return result; + } + catch (Throwable t) { + throw new MirLocalizerFailure(t); + } + } + } + + protected class ContentToTranslationFunction implements Generator.Function { + private EntityAdapter target; + private String targetId; + private String targetLanguageId; + + public ContentToTranslationFunction(EntityAdapter aTarget) { + target = aTarget; + targetId = (String) target.get("id"); + targetLanguageId = (String) target.get("to_language"); + } + + public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { + if (aParameters.size()!=1 || !(aParameters.get(0) instanceof String)) + throw new GeneratorExc("1 string parameter expected"); + + try { + String language = (String) aParameters.get(0); + String languageId = languageModule.languageIdForCode(language); + Object result = null; + + if (languageId != null && !targetLanguageId.equals(languageId)) { + result = target.getToOneRelation( + "is_published='t' and to_content=" + targetId + " and to_language='" + JDBCStringRoutines.escapeStringLiteral(languageId) + "'", + "id", "content"); + } + + if (result == null) + result = target; + + return result; + } + catch (Throwable t) { + t.printStackTrace(System.out); + throw new GeneratorFailure(t); + } + } + } + + protected class ContentToTranslationField implements EntityAdapterDefinition.CalculatedField { + public Object getValue(EntityAdapter anEntityAdapter) throws MirLocalizerFailure { + try { + return new ContentToTranslationFunction((EntityAdapter) anEntityAdapter.get("to_original")); + } + catch (Throwable t) { + throw new MirLocalizerFailure(t); + } + } + } } + diff --git a/source/mircoders/localizer/basic/MirBasicEmailArticleHandler.java b/source/mircoders/localizer/basic/MirBasicEmailArticleHandler.java index 73bea17f..39d0908f 100755 --- a/source/mircoders/localizer/basic/MirBasicEmailArticleHandler.java +++ b/source/mircoders/localizer/basic/MirBasicEmailArticleHandler.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Vector; +import java.util.Collections; import mir.config.MirPropertiesConfiguration; import mir.generator.Generator; @@ -59,7 +60,6 @@ import mircoders.storage.DatabaseContent; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; -import org.apache.struts.util.MessageResources; /** @@ -84,11 +84,11 @@ public class MirBasicEmailArticleHandler implements SessionHandler { } catch (Throwable t) { logger.fatal("Cannot load configuration: " + t.toString()); - + throw new RuntimeException("Cannot load configuration: " + t.toString()); } } - + public void processRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { if (aSession.getAttribute("initialRequest") == null) { aSession.setAttribute("initialRequest", "no"); @@ -98,17 +98,17 @@ public class MirBasicEmailArticleHandler implements SessionHandler { subsequentRequest(aRequest, aSession, aResponse); } } - + protected void initialRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { initializeSession(aRequest, aSession); makeInitialResponse(aRequest, aSession, aResponse); } - + protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure { /* do nothing for now */ - + } - + protected void makeInitialResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { /* if you do not supply an aid to this handler, it should return an error page */ /* if you supply a non-functioning/non-published aid to this handler, it should return an error page, but at a @@ -121,20 +121,20 @@ public class MirBasicEmailArticleHandler implements SessionHandler { else { aSession.setAttribute("email.aid",articleID); aResponse.setResponseValue("errors", null); - - String mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en"); + + String mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en"); aResponse.setResponseValue("mail_language",mail_language); aResponse.setResponseValue("mail_to",""); aResponse.setResponseValue("mail_from",""); aResponse.setResponseValue("mail_from_name",""); aResponse.setResponseValue("mail_comment",""); - + aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate")); - + } } - + protected boolean shouldSendMail(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{ if (validate(aRequest,aSession,aResponse,aValidationErrors)){ String to=aRequest.getParameter("mail_to"); @@ -142,22 +142,22 @@ public class MirBasicEmailArticleHandler implements SessionHandler { || to.indexOf('\n') != -1 || to.indexOf('\r') != -1 || to.indexOf(',') != -1) { - throw new SessionExc("Invalid to address"); // we might want to see this in a log, so it is not a validation error + throw new SessionExc("Invalid to address"); // we might want to see this in a log, so it is not a validation error } else return true; // go for it } else{ return false; //validation failed, but not in a potentially abusive way } - + } - - + + protected boolean validate(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{ - + if (ValidationHelper.testFieldEntered(aRequest, "mail_to", "validationerror.missing", aValidationErrors)) aResponse.setResponseValue("mail_to",aRequest.getParameter("mail_to")); if (ValidationHelper.testFieldEntered(aRequest, "mail_from", "validationerror.missing", aValidationErrors)) @@ -180,23 +180,23 @@ public class MirBasicEmailArticleHandler implements SessionHandler { } else { try { - ModuleContent contentModule = new ModuleContent(DatabaseContent.getInstance()); + ModuleContent contentModule = new ModuleContent(); EntityContent contentEnt = (EntityContent) contentModule.getById(aid); - + Map articleData = new HashMap(); articleData.put("article", MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", contentEnt)); articleData.put("languagecode", language); Map responseData = GeneratorHelper.makeBasicGenerationData(new Locale[] {new Locale(language,""),new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), "")},"bundles.open","bundles.open"); responseData.put("data",articleData); - + String emailAnArticleTemplate = configuration.getString("Localizer.OpenSession.email.MailTemplate"); - + Generator generator = MirGlobal.localizer().generators().makeOpenPostingGeneratorLibrary().makeGenerator(emailAnArticleTemplate); - + StringWriter theEmailStringWriter = new StringWriter(); PrintWriter theEmailPrintWriter = new PrintWriter(theEmailStringWriter); generator.generate(theEmailPrintWriter, responseData, logger); - + theEmailStringWriter.close(); theText = theEmailStringWriter.toString(); @@ -211,44 +211,45 @@ public class MirBasicEmailArticleHandler implements SessionHandler { } protected String getExtraEmailHeaders(Request aRequest,String to,String from) throws SessionExc { - + String headers = "To: " + to + "\nReply-To: "+ from+"\n";; if (configuration.getString("Localizer.OpenSession.email.includeSenderIP","no").equals("yes")) headers= headers+"X-Originating-IP: "+ ((HTTPRequestAdapter)aRequest).getRequest().getRemoteAddr() + "\n"; - + return headers; } protected String interpolateComment(String emailText,String comment,String from_name,String language) throws SessionExc{ - if (comment != null) { - MessageResources messages = MessageResources.getMessageResources("bundles.open"); - String commentTextToInsert=messages.getMessage(new Locale(language,""),"email.comment.intro", from_name)+"\n"; - - try { - emailText=StringRoutines.performRegularExpressionReplacement(emailText,"!COMMENT!",commentTextToInsert); - } - catch (Throwable e){ - throw new SessionExc("Problem doing regular expression replacement :" + e.toString()); - } + if (comment != null) { + String commentTextToInsert = + MirGlobal.getBundleFactory().getBundle("etc/bundles/open", new String[] { language }). + getValue("email.comment.intro" , Collections.singletonList(from_name)) + "\n"; + + try { + emailText = StringRoutines.performRegularExpressionReplacement(emailText, "!COMMENT!", commentTextToInsert); } - else{ - try { - emailText=StringRoutines.performRegularExpressionReplacement(emailText,"!COMMENT!",""); - } - catch (Throwable e){ - throw new SessionExc("Problem doing regular expression replacement " + e.toString()); - } + catch (Throwable e) { + throw new SessionExc("Problem doing regular expression replacement :" + e.toString()); + } + } + else { + try { + emailText = StringRoutines.performRegularExpressionReplacement(emailText, "!COMMENT!", ""); + } + catch (Throwable e) { + throw new SessionExc("Problem doing regular expression replacement " + e.toString()); } - return emailText; + } + return emailText; } - + protected boolean doTheSMTP(String aMessage,String aTo,String aFrom) throws SessionExc{ SMTPClient client=new SMTPClient(); try { int reply; client.connect(configuration.getString("ServletModule.OpenIndy.SMTPServer")); reply = client.getReplyCode(); - + if (!SMTPReply.isPositiveCompletion(reply)) { client.disconnect(); throw new SessionExc("SMTP server refused connection."); @@ -270,47 +271,46 @@ public class MirBasicEmailArticleHandler implements SessionHandler { } } throw new SessionExc(e.getMessage()); - } + } } - + protected boolean sendMail(Request aRequest,Session aSession,Response aResponse) throws SessionExc,SessionFailure { - String aid=aRequest.getParameter("mail_aid"); String to=aRequest.getParameter("mail_to"); String from=aRequest.getParameter("mail_from"); String from_name=aRequest.getParameter("mail_from_name"); String language=aRequest.getParameter("mail_language"); String comment=aRequest.getParameter("mail_comment"); - + String theEmailText=getEmailText((String) aSession.getAttribute("email.aid"),language); String headers=getExtraEmailHeaders(aRequest,to,from); theEmailText=interpolateComment(theEmailText,comment,from_name,language); - String message=headers+"\n"+theEmailText; + String message=headers+theEmailText; // the space between headers and content is in the template return doTheSMTP(message,to,from); - + } protected void subsequentRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { List validationErrors = new Vector(); if (shouldSendMail(aRequest,aSession,aResponse,validationErrors)){ - + sendMail(aRequest,aSession,aResponse); aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.DoneTemplate")); } else { - aResponse.setResponseValue("mail_comment",aRequest.getParameter("mail_comment")); //everything else is required + aResponse.setResponseValue("mail_comment",aRequest.getParameter("mail_comment")); //everything else is required aResponse.setResponseValue("errors",validationErrors); aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate")); } - + } - + /* String mail_language = aRequest.getParameter("mail_language"); if (mail_language == null) - mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en"); - + mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en"); + aResponse.setResponseValue("mail_language",mail_language); */ diff --git a/source/mircoders/localizer/basic/MirBasicGeneratorLocalizer.java b/source/mircoders/localizer/basic/MirBasicGeneratorLocalizer.java index d9b44079..05e43a26 100755 --- a/source/mircoders/localizer/basic/MirBasicGeneratorLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicGeneratorLocalizer.java @@ -55,36 +55,37 @@ public class MirBasicGeneratorLocalizer implements MirGeneratorLocalizer { protected void buildRepository(GeneratorLibraryRepository aRepository) { aRepository.registerLibraryFactory( "freemarker", - new FreemarkerGenerator.FreemarkerGeneratorLibraryFactory(MirGlobal.config().getString("Home") ) ); + new FreemarkerGenerator.FreemarkerGeneratorLibraryFactory( + MirGlobal.config().getHome())); aRepository.registerLibraryFactory( "velocity", - new VelocityGenerator.VelocityGeneratorLibraryFactory(MirGlobal.config().getString("Home") ) ); + new VelocityGenerator.VelocityGeneratorLibraryFactory(MirGlobal.config().getHome() ) ); aRepository.registerLibraryFactory( "tal", - new TALGenerator.TALGeneratorLibraryFactory(MirGlobal.config().getString("Home") ) ); + new TALGenerator.TALGeneratorLibraryFactory(MirGlobal.config().getHome() ) ); } - public Generator.GeneratorLibrary makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeProducerGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { try { - return repository.constructCompositeLibrary(MirGlobal.config().getString("Mir.Localizer.Producer.GeneratorLibrary")); + return repository.constructCompositeLibrary(MirGlobal.config().getStringArray("Mir.Localizer.Producer.GeneratorLibrary")); } catch (Throwable t) { throw new MirLocalizerFailure(t); } }; - public Generator.GeneratorLibrary makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeAdminGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { try { - return repository.constructCompositeLibrary(MirGlobal.config().getString("Mir.Localizer.Admin.GeneratorLibrary")); + return repository.constructCompositeLibrary(MirGlobal.config().getStringArray("Mir.Localizer.Admin.GeneratorLibrary")); } catch (Throwable t) { throw new MirLocalizerFailure(t); } }; - public Generator.GeneratorLibrary makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { + public Generator.Library makeOpenPostingGeneratorLibrary() throws MirLocalizerExc, MirLocalizerFailure { try { - return repository.constructCompositeLibrary(MirGlobal.config().getString("Mir.Localizer.OpenPosting.GeneratorLibrary")); + return repository.constructCompositeLibrary(MirGlobal.config().getStringArray("Mir.Localizer.OpenPosting.GeneratorLibrary")); } catch (Throwable t) { throw new MirLocalizerFailure(t); diff --git a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java index e3c77471..b3d33efe 100755 --- a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java @@ -29,13 +29,6 @@ */ package mircoders.localizer.basic; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Vector; -import java.util.Iterator; - import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; import mir.session.Request; @@ -49,6 +42,9 @@ import mircoders.localizer.MirAntiAbuseFilterType; import mircoders.localizer.MirLocalizerExc; import mircoders.localizer.MirLocalizerFailure; import mircoders.localizer.MirOpenPostingLocalizer; +import mircoders.localizer.basic.filters.ThrottleFilter; + +import java.util.*; public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { private List afterContentProducerTasks; @@ -88,16 +84,19 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { addSimpleAntiAbuseFilterType(new MirBasicAntiAbuseFilterTypes.RegularExpressionFilter("useragent", false, false, MirBasicAntiAbuseFilterTypes.RegularExpressionFilter.REQUEST_HEADERS, new String[] {"User-Agent"})); addSimpleAntiAbuseFilterType(new MirBasicAntiAbuseFilterTypes.IPFilter("ip")); + addSimpleAntiAbuseFilterType(new MirBasicAntiAbuseFilterTypes.RegularExpressionFilter("hostname", false, false, + MirBasicAntiAbuseFilterTypes.RegularExpressionFilter.REQUEST_HEADERS, new String[] {"hostname"})); + addSimpleAntiAbuseFilterType(new ThrottleFilter("throttle", 60*60*1000)); } public SessionHandler getOpenSessionHandler(String aSessionType) throws MirLocalizerExc, MirLocalizerFailure { -/* if (aSessionType!=null && aSessionType.equals("email")) + if (aSessionType!=null && aSessionType.equals("email")) return new MirBasicEmailArticleHandler(); -*/ + if (aSessionType!=null && aSessionType.equals("comment")) - return new MirBasicCommentPostingHandler(); + return new MirBasicCommentPostingHandler(configuration.getBoolean("Localizer.OpenSession.PersistentUploadedFiles")); - return new MirBasicArticlePostingHandler(); + return new MirBasicArticlePostingHandler(configuration.getBoolean("Localizer.OpenSession.PersistentUploadedFiles")); } public SessionHandler getOpenSessionHandler(Request aRequest, Session aSession) throws MirLocalizerExc, MirLocalizerFailure { @@ -116,7 +115,7 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { ProducerEngine.ProducerTask task = (ProducerEngine.ProducerTask) i.next(); try { - MirGlobal.producerEngine().addTask(task); + MirGlobal.getProducerEngine().addTask(task); } catch (Throwable t) { logger.error("Error adding content task "+task.getProducer()+"::"+task.getVerb()+": " + t.toString()); @@ -139,7 +138,7 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { ProducerEngine.ProducerTask task = (ProducerEngine.ProducerTask) i.next(); try { - MirGlobal.producerEngine().addTask(task); + MirGlobal.getProducerEngine().addTask(task); } catch (Throwable t) { logger.error("Error adding comment task "+task.getProducer()+"::"+task.getVerb()+": " + t.toString()); diff --git a/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java b/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java index 786fd626..d762c0d3 100755 --- a/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java +++ b/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java @@ -29,66 +29,51 @@ */ package mircoders.localizer.basic; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Vector; - import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; -import mir.session.Request; -import mir.session.Response; -import mir.session.Session; -import mir.session.SessionExc; -import mir.session.SessionFailure; -import mir.session.SessionHandler; -import mir.session.UploadedFile; -import mir.session.ValidationError; +import mir.session.*; import mir.storage.StorageObject; import mir.util.ExceptionFunctions; +import mir.util.FileFunctions; import mircoders.global.MirGlobal; import mircoders.module.ModuleMediaType; +import mircoders.media.UnsupportedMediaTypeExc; + +import java.io.*; +import java.util.*; /** - * - *

Title: Experimental session handler for comment postings

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 + * Extensible handler for open postings. + * Behaviour can be altered by overriding methods. */ - public abstract class MirBasicPostingSessionHandler implements SessionHandler { - protected LoggerWrapper logger; - protected MirPropertiesConfiguration configuration; + protected static LoggerWrapper logger = new LoggerWrapper("Localizer.OpenPosting"); + protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();; + + /** Previously uploaded files */ + protected List attachments; + /** counter to generate unique field names for uploaded files */ + protected int uploadedFileIndex = 0; private String normalResponseGenerator; private String dupeResponseGenerator; private String unsupportedMediaTypeResponseGenerator; private String finalResponseGenerator; + private boolean persistentUploadedFiles; - public MirBasicPostingSessionHandler() { - logger = new LoggerWrapper("Localizer.OpenPosting"); - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (Throwable t) { - logger.fatal("Cannot load configuration: " + t.toString()); - - throw new RuntimeException("Cannot load configuration: " + t.toString()); - } + public MirBasicPostingSessionHandler(boolean aPersistentUploadedFiles) { + attachments = new ArrayList(); + persistentUploadedFiles = aPersistentUploadedFiles; } protected void setNormalResponseGenerator(String aGenerator) { normalResponseGenerator = aGenerator; } - protected void setResponseGenerators(String aNormalResponseGenerator, String aDupeResponseGenerator, - String anUnsupportedMediaTypeResponseGenerator, String aFinalResponseGenerator) { + protected void setResponseGenerators(String aNormalResponseGenerator, + String aDupeResponseGenerator, String anUnsupportedMediaTypeResponseGenerator, + String aFinalResponseGenerator) { setNormalResponseGenerator(aNormalResponseGenerator); dupeResponseGenerator = aDupeResponseGenerator; unsupportedMediaTypeResponseGenerator = anUnsupportedMediaTypeResponseGenerator; @@ -117,10 +102,30 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { makeInitialResponse(aRequest, aSession, aResponse); } + protected void processAttachments(Request aRequest, Session aSession, Response aResponse) { + Iterator i = attachments.iterator(); + while (i.hasNext()) { + Attachment attachment = (Attachment) i.next(); + try{ + processAttachment(aRequest, aSession, attachment); + } + catch (Throwable t) { + try { + processAttachmentError(aRequest, aSession, attachment, t); + } + catch (Throwable u) { + } + } + } + } + public void subsequentRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { try { try { - List validationErrors = new Vector(); + List validationErrors = new ArrayList(); + + preprocessPreviousAttachments(aRequest, aSession); + preProcessNewAttachments(aRequest, aSession); if (!shouldProcessRequest(aRequest, aSession, validationErrors)) { initializeResponseData(aRequest, aSession, aResponse); @@ -128,10 +133,8 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { } else { preProcessRequest(aRequest, aSession); - Iterator i = aRequest.getUploadedFiles().iterator(); - while (i.hasNext()) { - processUploadedFile(aRequest, aSession, (UploadedFile) i.next()); - } + + processAttachments(aRequest, aSession, aResponse); postProcessRequest(aRequest, aSession); initializeResponseData(aRequest, aSession, aResponse); makeFinalResponse(aRequest, aSession, aResponse); @@ -151,6 +154,11 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { } } + /** + * Initializes a session. + * This may happen in the case of a new session being initiated, but also + * when an older session gets re-initiated after a session timeout. + */ protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure { if (MirGlobal.abuse().getOpenPostingPassword()) { String password = (String) aSession.getAttribute("password"); @@ -163,29 +171,30 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { aSession.deleteAttribute("password"); } - logger.debug("referrer = " + aRequest.getHeader("Referer")); - aSession.setAttribute("referer", aRequest.getHeader("Referer")); } + /** + * Called every time a response is being prepared. + * This may be at the initial response, or on a subsequent one. + */ protected void initializeResponseData(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { int nrMediaItems = configuration.getInt("ServletModule.OpenIndy.DefaultMediaUploadItems", 5); if (aSession.getAttribute("nrmediaitems")!=null) { nrMediaItems = ((Integer) aSession.getAttribute("nrmediaitems")).intValue(); } + try { nrMediaItems = Math.min(configuration.getInt("ServletModule.OpenIndy.MaxMediaUploadItems"), Integer.parseInt(aRequest.getParameter("nrmediaitems"))); } catch (Throwable t) { } - aSession.setAttribute("nrmediaitems", new Integer(nrMediaItems)); - List mediaItems = new Vector(); - int i=0; + aSession.setAttribute("nrmediaitems", new Integer(nrMediaItems)); - while (i0) { + final File sourceFile = new File(FTPDirectory, fileName); + + if (sourceFile.getParentFile().equals(FTPDirectory)) { + preprocessNewAttachment(aRequest, aSession, new UploadedFile() { + public void writeToFile(File aFile) throws SessionFailure { + try { + FileFunctions.move(sourceFile, aFile); + } + catch (IOException e) { + throw new SessionFailure(e); + } + } + + public InputStream getInputStream() throws SessionFailure { + try { + return new FileInputStream(sourceFile); + } + catch (IOException e) { + throw new SessionFailure(e); + } + } + + public String getFileName() { + return fileName; + } + + public String getFieldName() { + return fieldName; + } + + public String getContentType() { + return null; + } + }); + } + } + } + } + } } protected void makeInitialResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure { @@ -210,18 +356,19 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { }; protected void makeErrorResponse(Request aRequest, Session aSession, Response aResponse, Throwable anError) throws SessionExc, SessionFailure { - anError.printStackTrace(); Throwable rootCause = ExceptionFunctions.traceCauseException(anError); if (rootCause instanceof DuplicatePostingExc) aResponse.setResponseGenerator(dupeResponseGenerator); - if (rootCause instanceof ModuleMediaType.UnsupportedMimeTypeExc) { - aResponse.setResponseValue("mimetype", ((ModuleMediaType.UnsupportedMimeTypeExc) rootCause).getMimeType()); + if (rootCause instanceof UnsupportedMediaTypeExc) { + aResponse.setResponseValue("mimetype", ((UnsupportedMediaTypeExc) rootCause).getMimeType()); aResponse.setResponseGenerator(unsupportedMediaTypeResponseGenerator); } else { - aResponse.setResponseValue("errorstring", anError.getMessage()); - aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.ErrorTemplate")); + List errors = new ArrayList(); + errors.add(new ValidationError("", "general.unexpectederror", + new Object[] {anError.getMessage()})); + makeResponse(aRequest, aSession, aResponse, errors); } }; @@ -229,13 +376,23 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { aResponse.setResponseGenerator(configuration.getString("ServletModule.OpenIndy.PostingDisabledTemplate")); } + /** + * + */ protected void preProcessRequest(Request aRequest, Session aSession) throws SessionExc, SessionFailure { }; - public void processUploadedFile(Request aRequest, Session aSession, UploadedFile aFile) throws SessionExc, SessionFailure { + public void processAttachment(Request aRequest, Session aSession, Attachment aFile) throws SessionExc, SessionFailure { + }; + public void processAttachmentError(Request aRequest, Session aSession, Attachment aFile, Throwable anError) { }; protected void postProcessRequest(Request aRequest, Session aSession) throws SessionExc, SessionFailure { }; + /** + * Determine whether the request shoudl be processed: that is, the validate, + * preprocess, postprocess methods should be called to perform validations, + * store data, etc + */ protected boolean shouldProcessRequest(Request aRequest, Session aSession, List aValidationErrors) throws SessionExc, SessionFailure { if (aRequest.getParameter("post")==null) return false; @@ -245,6 +402,13 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { } } + /** + * Method used to validate user input. + * Multiple {@link ValidationError}s may be added to the + * aResults parameter. + * The request is considered validated if, after calling this method, + * aResults is empty. + */ protected void validate(List aResults, Request aRequest, Session aSession) throws SessionExc, SessionFailure { String password = (String) aSession.getAttribute("password"); @@ -263,7 +427,6 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { * * @return a password, to be used once */ - protected String generateOnetimePassword() { Random r = new Random(); int random = r.nextInt(); @@ -279,20 +442,14 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { return returnString.substring(5); } - /** - * - * @param aRequest - * @param aStorage - * @return - * @throws SessionExc - * @throws SessionFailure + * Method to filter the attributes and their values of a request + * based on the fields of a storage object. */ - - protected static final Map getIntersectingValues(Request aRequest, StorageObject aStorage) throws SessionExc, SessionFailure { + protected static final Map getIntersectingValues(Request aRequest, StorageObject aStorage) throws SessionFailure { Map result = new HashMap(); - Iterator i = aStorage.getFields().iterator(); + Iterator i = aStorage.getFieldNames().iterator(); while (i.hasNext()) { String fieldName = (String) i.next(); @@ -304,10 +461,64 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { return result; } + /** + * Exception to be thrown when an article or comment was already posted + */ protected static class DuplicatePostingExc extends SessionExc { public DuplicatePostingExc(String aMessage) { super(aMessage); } } + /** + * A file that has been attached to a session + */ + protected static class Attachment implements UploadedFile { + private UploadedFile uploadedFile; + private String filename; + private String fieldName; + private String contentType; + private Map attributes; + + public Attachment(UploadedFile anUploadedFile, String aFilename, String aFieldName, String aContentType) { + attributes = new HashMap(); + filename = aFilename; + fieldName = aFieldName; + contentType = aContentType; + uploadedFile = anUploadedFile; + } + + public void writeToFile(File aFile) throws SessionExc, SessionFailure { + uploadedFile.writeToFile(aFile); + } + + public InputStream getInputStream() throws SessionExc, SessionFailure { + return uploadedFile.getInputStream(); + } + + public String getFileName() { + return filename; + } + + public String getFieldName() { + return fieldName; + } + + public String getContentType() { + return contentType; + } + + public String getAttribute(String anAttribute) { + return (String) attributes.get(anAttribute); + } + + public void setAttribute(String anAttribute, String aValue) { + attributes.put(anAttribute, aValue); + } + + public Map getAllAttributes() { + return Collections.unmodifiableMap(attributes); + } + } } + diff --git a/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java b/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java index c9461243..8b967486 100755 --- a/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java @@ -29,28 +29,35 @@ */ package mircoders.localizer.basic; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - import mir.config.MirPropertiesConfiguration; import mir.entity.adapter.EntityAdapter; import mir.entity.adapter.EntityIteratorAdapter; +import mir.generator.Generator; +import mir.generator.GeneratorExc; +import mir.generator.GeneratorFailure; import mir.log.LoggerWrapper; import mir.misc.StringUtil; -import mir.util.GeneratorDateTimeFunctions; -import mir.util.GeneratorExpressionFunctions; -import mir.util.GeneratorFormatAdapters; -import mir.util.GeneratorHTMLFunctions; -import mir.util.GeneratorIntegerFunctions; -import mir.util.GeneratorListFunctions; -import mir.util.GeneratorRegularExpressionFunctions; -import mir.util.GeneratorStringFunctions; +import mir.util.*; +import mir.util.generator.ReflectionGeneratorFunctionsAdapter; import mircoders.global.MirGlobal; import mircoders.localizer.MirLocalizerExc; import mircoders.localizer.MirLocalizerFailure; import mircoders.localizer.MirProducerAssistantLocalizer; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.tidy.Tidy; +import org.w3c.tidy.Configuration; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantLocalizer { protected LoggerWrapper logger; @@ -60,7 +67,6 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL Iterator i; Map configMap = new HashMap(); - Map utilityMap = new HashMap(); logger = new LoggerWrapper("Localizer.ProducerAssistant"); @@ -82,27 +88,9 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL // "new": configMap.putAll(MirPropertiesConfiguration.instance().allSettings()); - utilityMap.put("compressWhitespace", new freemarker.template.utility.CompressWhitespace()); - utilityMap.put("encodeHTML", new GeneratorHTMLFunctions.encodeHTMLGeneratorFunction()); - utilityMap.put("prettyEncodeHTML", new GeneratorHTMLFunctions.prettyEncodeHTMLGeneratorFunction()); - utilityMap.put("encodeXML", new GeneratorHTMLFunctions.encodeXMLGeneratorFunction()); - utilityMap.put("encodeURI", new GeneratorHTMLFunctions.encodeURIGeneratorFunction()); - utilityMap.put("subString", new GeneratorStringFunctions.subStringFunction()); - utilityMap.put("subList", new GeneratorListFunctions.subListFunction()); - utilityMap.put("listSize", new GeneratorListFunctions.listSizeFunction()); - utilityMap.put("isOdd", new GeneratorIntegerFunctions.isOddFunction()); - utilityMap.put("increment", new GeneratorIntegerFunctions.incrementFunction()); - utilityMap.put("evaluate", new GeneratorExpressionFunctions.evaluateExpressionFunction()); - utilityMap.put("constructString", new GeneratorStringFunctions.constructStructuredStringFunction()); - utilityMap.put("parseStructuredString", new GeneratorStringFunctions.structuredStringParserFunction()); - utilityMap.put("escapeJDBCString", new GeneratorStringFunctions.jdbcStringEscapeFunction()); - utilityMap.put("regexpreplace", new GeneratorRegularExpressionFunctions.regularExpressionReplaceFunction()); - utilityMap.put("regexpmatch", new GeneratorRegularExpressionFunctions.regularExpressionMatchFunction()); - utilityMap.put("datetime", new GeneratorDateTimeFunctions.DateTimeFunctions( - MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone"))); - aValueSet.put("config", configMap); - aValueSet.put("utility", utilityMap); + + aValueSet.put("utility", new Utility()); aValueSet.put("languages", new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "language")); @@ -133,6 +121,7 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL commentStatusMap.put(commentStatus.get("name"), commentStatus.get("id")); } aValueSet.put("commentstatus", commentStatusMap); + aValueSet.put("languageCodeToId", new getLanguageIdFunction()); } catch (Throwable t) { logger.error("initializeGenerationValueSet: Exception while collecting comment statuses" + t.getMessage()); @@ -140,6 +129,52 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL } }; + public static class getLanguageIdFunction implements Generator.Function { + private Map languageCodeToId; + private String otherLanguageId; + private LoggerWrapper logger = new LoggerWrapper("Localizer.Earth.getLanguageIdFunction"); + + public getLanguageIdFunction() throws MirLocalizerFailure { + try { + otherLanguageId = ""; + languageCodeToId = new HashMap(); + + Iterator i = new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "language"); + while (i.hasNext()) { + EntityAdapter language = (EntityAdapter) i.next(); + if (language.get("code").equals("ot")) + otherLanguageId = (String) language.get("id"); + + languageCodeToId.put(language.get("code"), language.get("id")); + } + } + catch (Throwable t) { + logger.error(t.toString()); + + throw new MirLocalizerFailure(t); + } + } + + public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure { + try { + if (aParameters.size() != 1) + throw new GeneratorExc("getLanguageIdFunction: 1 parameter expected: language-code"); + + String result = (String) languageCodeToId.get(aParameters.get(0)); + if (result == null) + result = otherLanguageId; + + return result; + } + catch (GeneratorExc e) { + throw e; + } + catch (Throwable t) { + throw new GeneratorFailure("getLanguageIdFunction: " + t.getMessage(), t); + } + }; + } + public String filterNonHTMLText(String aText) { @@ -162,8 +197,139 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL throw new RuntimeException(t.toString()); } } - public String filterHTMLText(String aText) { - return StringUtil.deleteForbiddenTags(aText); + try { + StringWriter out = new StringWriter(); + Tidy tidy = new Tidy(); + ByteArrayInputStream in = new ByteArrayInputStream(aText.getBytes("UTF8")); + tidy.setMakeClean(true); + tidy.setCharEncoding(Configuration.UTF8); + tidy.setErrout(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + print(tidy.parseDOM(in, null), out); + + return out.toString(); + } + catch (IOException e) { + return e.getMessage(); + } + } + + private boolean checkAttr(String attrName) { + if (attrName.equals("onLoad") || attrName.equals("onClick") || attrName.equals("onFocus") || attrName.equals("onBlur") || attrName.equals("onMouseOver") || attrName.equals("onMouseOut") || attrName.equals("style") || attrName.equals("STYLE") || attrName.equals("height") || attrName.equals("width") || attrName.equals("HEIGHT") || attrName.equals("WIDTH")) + return false; + else + return true; + + } + + private boolean checkNode(String nodeName) { + if (nodeName.equals("a") || + nodeName.equals("img") || + nodeName.equals("h1") || + nodeName.equals("h2") || + nodeName.equals("h3") || + nodeName.equals("h4") || + nodeName.equals("h5") || + nodeName.equals("h6") || + nodeName.equals("br") || + nodeName.equals("form") || + nodeName.equals("input") || + nodeName.equals("hr") || + nodeName.equals("strong") || + nodeName.equals("font") || + nodeName.equals("b") || + nodeName.equals("i") || + nodeName.equals("em") || + nodeName.equals("p") || + nodeName.equals("table") || + nodeName.equals("tr") || + nodeName.equals("td") || + nodeName.equals("th") || + nodeName.equals("ul") || + nodeName.equals("ol") || + nodeName.equals("li") + ) { + return true; + } else { + + return false; + } + } + + private void print(Node node, StringWriter out) throws IOException { + if (node == null) { + return; + } + int type = node.getNodeType(); + boolean canOutput = checkNode(node.getNodeName()); + + switch (type) { + + case Node.DOCUMENT_NODE: + + print(((Document) node).getDocumentElement(), out); + out.flush(); + break; + + case Node.ELEMENT_NODE: + if (canOutput) { + out.write('<'); + + out.write(node.getNodeName()); + NamedNodeMap attrs = node.getAttributes(); + + for (int i = 0; i < attrs.getLength(); i++) { + String attrName = attrs.item(i).getNodeName(); + if (checkAttr(attrName)) { + out.write(' '); + out.write(attrs.item(i).getNodeName()); + out.write("=\""); + + out.write(attrs.item(i).getNodeValue()); + out.write('"'); + } + } + + if (node.getChildNodes()==null || node.getChildNodes().getLength()==0) { + out.write("/"); + } + out.write('>'); + } + NodeList children = node.getChildNodes(); + if (children != null) { + int len = children.getLength(); + for (int i = 0; i < len; i++) { + print(children.item(i), out); + } + } + break; + + case Node.TEXT_NODE: + out.write(node.getNodeValue()); + break; + + } + + if (type == Node.ELEMENT_NODE && canOutput && node.getChildNodes()!=null && node.getChildNodes().getLength()>0) { + out.write("'); + } + + out.flush(); + } + + public static class Utility extends ReflectionGeneratorFunctionsAdapter { + public Utility () { + super(new MirBasicUtilityFunctions()); + } + public Object getDatetime() { + return new GeneratorDateTimeFunctions.DateTimeFunctions( + MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")); + } + + public Object getCompressWhitespace() { + return new freemarker.template.utility.CompressWhitespace(); + } } } diff --git a/source/mircoders/localizer/basic/MirBasicProducerLocalizer.java b/source/mircoders/localizer/basic/MirBasicProducerLocalizer.java index 8b4f9879..66d55962 100755 --- a/source/mircoders/localizer/basic/MirBasicProducerLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicProducerLocalizer.java @@ -40,11 +40,9 @@ import mir.entity.adapter.EntityAdapterModel; import mir.generator.Generator; import mir.generator.WriterEngine; import mir.log.LoggerWrapper; -import mir.producer.ProducerFactory; import mir.producer.reader.DefaultProducerNodeBuilders; import mir.producer.reader.ProducerConfigReader; import mir.producer.reader.ProducerNodeBuilderLibrary; -import mir.util.FileMonitor; import mir.util.StringRoutines; import mircoders.global.MirGlobal; import mircoders.global.ProducerEngine; @@ -54,15 +52,11 @@ import mircoders.localizer.MirProducerLocalizer; import mircoders.producer.reader.SupplementalProducerNodeBuilders; public class MirBasicProducerLocalizer implements MirProducerLocalizer { - private List producerFactories; - private Map nameToFactory; - private Map producerRecipes; private List producerRecipeNames; - protected FileMonitor fileMonitor; protected EntityAdapterModel model; - protected Generator.GeneratorLibrary generatorLibrary; + protected Generator.Library generatorLibrary; protected WriterEngine writerEngine; protected LoggerWrapper logger; @@ -79,8 +73,10 @@ public class MirBasicProducerLocalizer implements MirProducerLocalizer { try { List parts = StringRoutines.separateString(recipes[i], "="); if (parts.size() == 2) { - producerRecipes.put(parts.get(0), ProducerEngine.ProducerTask.parseProducerTaskList( (String) parts.get(1))); - producerRecipeNames.add(parts.get(0)); + String key = ((String) parts.get(0)).trim(); + producerRecipes.put(key, ProducerEngine.ProducerTask.parseProducerTaskList( + ((String) parts.get(1)).trim())); + producerRecipeNames.add(key); } else { throw new Exception("'=' expected"); @@ -95,14 +91,15 @@ public class MirBasicProducerLocalizer implements MirProducerLocalizer { String allNewProducers = MirGlobal.config().getString("Mir.Localizer.Producer.AllNewProducers"); if (allNewProducers!=null && allNewProducers.length()>0) { producerRecipes.put("allnew", ProducerEngine.ProducerTask.parseProducerTaskList(allNewProducers)); - producerRecipeNames.add("allnew"); + + if (!producerRecipeNames.contains("allnew")) { + producerRecipeNames.add("allnew"); + } } - producerFactories = new Vector(); model = MirGlobal.localizer().dataModel().adapterModel(); generatorLibrary = MirGlobal.localizer().generators().makeProducerGeneratorLibrary(); writerEngine = MirGlobal.localizer().generators().makeWriterEngine(); - nameToFactory = new HashMap(); } catch (Throwable t) { logger.error("MirBasicProducerLocalizer(): Exception "+t.getMessage()); @@ -122,10 +119,11 @@ public class MirBasicProducerLocalizer implements MirProducerLocalizer { ProducerEngine.ProducerTask task = (ProducerEngine.ProducerTask) i.next(); try { - MirGlobal.producerEngine().addTask(task); + MirGlobal.getProducerEngine().addTask(task); } catch (Throwable t) { - logger.error("Error recipe "+aName+" tasks "+task.getProducer()+"::"+task.getVerb()+": " + t.toString()); + logger.error("Error recipe "+aName+" tasks "+ + task.getProducer()+"::"+task.getVerb()+": " + t.toString()); } } } @@ -133,65 +131,46 @@ public class MirBasicProducerLocalizer implements MirProducerLocalizer { throw new MirLocalizerExc("Unknown recipe name: " + aName); } - public List factories() throws MirLocalizerExc { - if (fileMonitor==null || producerFactories == null || fileMonitor.hasChanged()) { + /** + * Loads factories from a file with a {@link ProducerConfigReader} + */ + public List loadFactories() throws MirLocalizerExc { try { - List newProducers = new Vector(); - FileMonitor newFileMonitor = new FileMonitor(); - setupFactories(newProducers, newFileMonitor); - - producerFactories = newProducers; - fileMonitor = newFileMonitor; - logger.info("MirBasicProducerLocalizer.factories(): successfully setup factories"); - - nameToFactory.clear(); - Iterator i = producerFactories.iterator(); - while (i.hasNext()) { - ProducerFactory factory = (ProducerFactory) i.next(); - nameToFactory.put(factory.getName(), factory); - } + List producers = new Vector(); + ProducerConfigReader reader; + ProducerNodeBuilderLibrary library = new ProducerNodeBuilderLibrary(); + setupProducerNodeBuilderLibrary(library); + reader = new ProducerConfigReader(); + File inputFile = + MirGlobal.config().getFile("Mir.Localizer.ProducerConfigFile"); + reader.parse(inputFile, library, producers); + + logger.info("MirBasicProducerLocalizer.loadFactories(): successfully loaded factories"); + + return producers; } catch (Throwable t) { - logger.error("MirBasicProducerLocalizer.factories(): Unable to setup factories: "+t.getMessage()); - t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + logger.error("MirBasicProducerLocalizer.loadFactories(): Unable to load factories: "+ + t.getMessage()); + throw new MirLocalizerFailure(t); } - } - - return producerFactories; }; - public ProducerFactory getFactoryForName(String aName) { - try { - factories(); - } - catch (Throwable t) { - } - - return (ProducerFactory) nameToFactory.get(aName); - } - + /** + * Sets up a {@link ProducerNodeBuilderLibrary} for use by the producer + * definition reader. Can be overridden by subclasses to tweak the standard + * library. + */ protected void setupProducerNodeBuilderLibrary(ProducerNodeBuilderLibrary aLibrary) throws MirLocalizerFailure { try { DefaultProducerNodeBuilders.registerBuilders( aLibrary, model, generatorLibrary, writerEngine, - MirGlobal.config().getString("Home"), MirGlobal.config().getString("Producer.StorageRoot")); - SupplementalProducerNodeBuilders.registerBuilders(aLibrary, model); + MirGlobal.config().getHome(), MirGlobal.config().getFile("Producer.StorageRoot")); + SupplementalProducerNodeBuilders.registerBuilders(aLibrary, MirGlobal.config().getHome()); } catch (Throwable t) { throw new MirLocalizerFailure(t.getMessage(), t); } } - protected void setupFactories(List aFactories, FileMonitor aFileMonitor) throws MirLocalizerExc, MirLocalizerFailure { - ProducerConfigReader reader; - ProducerNodeBuilderLibrary library = new ProducerNodeBuilderLibrary(); - setupProducerNodeBuilderLibrary(library); - - aFileMonitor.clear(); - reader = new ProducerConfigReader(); - - File inputFile = new File(MirGlobal.config().getString("Home"), MirGlobal.config().getString("Mir.Localizer.ProducerConfigFile")); - aFileMonitor.addFile(inputFile); - reader.parse(inputFile, library, aFactories); - } } diff --git a/source/mircoders/localizer/basic/MirBasicUtilityFunctions.java b/source/mircoders/localizer/basic/MirBasicUtilityFunctions.java new file mode 100755 index 00000000..363b9972 --- /dev/null +++ b/source/mircoders/localizer/basic/MirBasicUtilityFunctions.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.localizer.basic; + +import mir.util.*; +import mir.config.MirPropertiesConfiguration; + +import java.util.Collections; +import java.util.List; + +public class MirBasicUtilityFunctions { + public String encodeXML(Object anObject) throws Exception { + return HTMLRoutines.encodeXML(StringRoutines.interpretAsString(anObject)); + } + + public String encodeHTML(Object aString) throws Exception { + return HTMLRoutines.encodeHTML(StringRoutines.interpretAsString(aString)); + } + + public String prettyEncodeHTML(Object aString) throws Exception { + return HTMLRoutines.prettyEncodeHTML(StringRoutines.interpretAsString(aString)); + } + + public String encodeURI(Object aString) throws Exception { + return HTMLRoutines.encodeURL(StringRoutines.interpretAsString(aString)); + } + + public String encodeURI(Object aString, Object anEncoding) throws Exception { + return HTMLRoutines.encodeURL( + StringRoutines.interpretAsString(aString), + StringRoutines.interpretAsString(anEncoding)); + } + + public String subString(Object aString, Object aFrom) throws Exception { + return StringRoutines.interpretAsString(aString).substring(StringRoutines.interpretAsInteger(aFrom)); + } + + public String subString(Object aString, Object aFrom, Object aLength) throws Exception { + int length = StringRoutines.interpretAsInteger(aLength); + String target = StringRoutines.interpretAsString(aString); + if (length<0 || length>target.length()) { + length=target.length(); + } + + return target.substring(StringRoutines.interpretAsInteger(aFrom), length); + } + + public String escapeJDBCString(Object aString) throws Exception { + return JDBCStringRoutines.escapeStringLiteral(StringRoutines.interpretAsString(aString)); + } + + public String constructString(Object aString) throws Exception { + if (aString==null) + return StructuredContentParser.constructStringLiteral(""); + else + return StructuredContentParser.constructStringLiteral(StringRoutines.interpretAsString(aString)); + } + + public Object parseStructuredString(Object aString) throws Exception { + if (aString==null) + return null; + else + return StructuredContentParser.parse(StringRoutines.interpretAsString(aString)); + } + + public boolean isOdd(Object anInteger) throws Exception { + return (StringRoutines.interpretAsInteger(anInteger) & 1) == 1; + } + + public int increment(Object anInteger) throws Exception { + final Integer ONE = new Integer(1); + + return increment(anInteger, ONE); + } + + public int increment(Object anInteger, Object anIncrement) throws Exception { + return StringRoutines.interpretAsInteger(anInteger) + + StringRoutines.interpretAsInteger(anIncrement); + } + + public Object subList(Object aList, Object aSkip) throws Exception { + return subList(aList, aSkip, new Integer(-1)); + } + + public Object subList(Object aList, Object aSkip, Object aMaxSize) throws Exception { + int skip = StringRoutines.interpretAsInteger(aSkip); + int maxSize = StringRoutines.interpretAsInteger(aMaxSize); + + if (aList instanceof RewindableIterator) + return new SubsetIterator((RewindableIterator) aList, skip, maxSize); + else { + List list = (List) aList; + + if (skip>=list.size()) + return Collections.EMPTY_LIST; + if (maxSize<0 || (skip+maxSize)>=list.size()) + return list.subList(skip, list.size()); + else + return list.subList(skip, skip+maxSize); + } + } + + public int listSize(RewindableIterator anIterator) { + anIterator.rewind(); + int result=0; + + while (anIterator.hasNext()) { + result++; + anIterator.next(); + } + + anIterator.rewind(); + + return result; + } + + public int listSize(List aList) { + return aList.size(); + } + + public Object evaluate(Object aTarget, String anExpression) throws Exception { + return ParameterExpander.expandExpression(aTarget, anExpression); + } + + public String regexpreplace(String aString, String anExpression, String aReplacement) { + return StringRoutines.performRegularExpressionReplacement(aString, anExpression, aReplacement); + } + + public boolean regexpmatch(String aString, String anExpression) { + return StringRoutines.performRegularExpressionSearch(aString, anExpression); + } +} diff --git a/source/mircoders/localizer/basic/actions/ArticleTopicAction.java b/source/mircoders/localizer/basic/actions/ArticleTopicAction.java new file mode 100755 index 00000000..7770ff3a --- /dev/null +++ b/source/mircoders/localizer/basic/actions/ArticleTopicAction.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.localizer.basic.actions; + +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +import mir.entity.adapter.EntityAdapter; +import mircoders.localizer.MirLocalizerExc; +import mircoders.localizer.MirLocalizerFailure; +import mircoders.localizer.basic.MirBasicAdminInterfaceLocalizer; +import mircoders.storage.DatabaseContentToTopics; + +public class ArticleTopicAction implements MirBasicAdminInterfaceLocalizer.MirSimpleEntityOperation{ + private String name; + private List deleteTopics; + private List addTopics; + + public ArticleTopicAction(String aName, int[] aDeleteTopics, int[] anAddTopics) { + name = aName; + deleteTopics = new ArrayList(); + for (int i=0; i< aDeleteTopics.length; i++) { + deleteTopics.add(Integer.toString(aDeleteTopics[i])); + } + addTopics = new ArrayList(); + for (int i=0; i< anAddTopics.length; i++) { + addTopics.add(Integer.toString(anAddTopics[i])); + } + } + + public String getName() { + return name; + } + + public boolean isAvailable(EntityAdapter anEntity) throws MirLocalizerExc, MirLocalizerFailure { + return true; + } + + public void perform(EntityAdapter aUser, EntityAdapter anEntity) throws MirLocalizerExc, MirLocalizerFailure { + DatabaseContentToTopics db = DatabaseContentToTopics.getInstance(); + + List topicsToSet = new ArrayList(db.getTopicsOfContent(anEntity.getEntity().getId())); + + topicsToSet.removeAll(deleteTopics); + topicsToSet.addAll(addTopics); + + db.setTopics(anEntity.getEntity().getId(), topicsToSet); + } + public void perform2(EntityAdapter aUser, EntityAdapter anEntity) throws MirLocalizerExc, MirLocalizerFailure { + DatabaseContentToTopics db = DatabaseContentToTopics.getInstance(); + + List integerTopicsToSet = new ArrayList(db.getTopicsOfContent(anEntity.getEntity().getId())); + List topicsToSet = new ArrayList(); + Iterator i = integerTopicsToSet.iterator(); + while (i.hasNext()) { + topicsToSet.add(i.next().toString()); + } + + topicsToSet.removeAll(deleteTopics); + topicsToSet.addAll(addTopics); + + db.setTopics(anEntity.getEntity().getId(), topicsToSet); + } +} diff --git a/source/mircoders/localizer/basic/filters/ThrottleFilter.java b/source/mircoders/localizer/basic/filters/ThrottleFilter.java new file mode 100755 index 00000000..65b47320 --- /dev/null +++ b/source/mircoders/localizer/basic/filters/ThrottleFilter.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.localizer.basic.filters; + +import mircoders.localizer.basic.MirBasicAntiAbuseFilterTypes; +import mircoders.entity.EntityComment; + +import java.util.*; + +import mir.util.StringRoutines; +import mir.entity.Entity; +import mir.session.Request; + +/** + * A ip-based throttling filter. + * + *

+ * Expressions have the form

* Of course it implements the MirMediaHandler interface. * - * @see mir.media.MirMediaHandler + * @see mir.media.MediaHandler * @author mh - * @version $Id: MediaHandlerGeneric.java,v 1.20.2.6 2004/01/18 17:30:58 zapata Exp $ + * @version $Id: MediaHandlerGeneric.java,v 1.20.2.7 2004/11/21 22:07:14 zapata Exp $ */ -public class MediaHandlerGeneric implements MediaHandler +public class MediaHandlerGeneric extends AbstractMediaHandler { - protected static MirPropertiesConfiguration configuration; - protected static String imageHost; - protected static String imageRoot; - - protected LoggerWrapper logger; - - static { - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (MirPropertiesConfiguration.PropertiesConfigExc e) { - } - imageHost = configuration.getString("Producer.Image.Host"); - imageRoot = configuration.getString("Producer.ImageRoot"); - } + protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); - public MediaHandlerGeneric() { - logger = new LoggerWrapper("Media.Generic"); - } + protected LoggerWrapper logger = new LoggerWrapper("Media.Generic"); - public void store (InputStream in, Entity ent, Entity mediaTypeEnt ) throws MediaExc, MediaFailure { - String ext = mediaTypeEnt.getFieldValue("name"); - String mediaFname = ent.getId() + "." + ext; - String date = ent.getFieldValue("date"); - String datePath = StringUtil.webdbDate2path(date); - try { - long size = FileUtil.write(getStoragePath() + File.separator + datePath + - File.separator + mediaFname, in); - ent.setFieldValue("publish_path", datePath + mediaFname); - ent.setFieldValue("size", new Long(size).toString()); - ent.update(); - } - catch (Throwable e) { - logger.error("MediaHandlerGeneric.set: " + e.toString()); - throw new MediaFailure(e); - } + /** {@inheritDoc} */ + public void store(File aFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + try { + FileFunctions.move(aFile, getStorageFile(aMedia, aMediaType)); + + aMedia.setFieldValue("publish_path", getRelativeStorageFile(aMedia, aMediaType)); + aMedia.setFieldValue("size", Long.toString(getStorageFile(aMedia, aMediaType).length())); + aMedia.update(); + } + catch (Throwable e) { + logger.error("MediaHandlerGeneric.set: " + e.toString()); + throw new MediaFailure(e); } + } - public void produce (Entity ent, Entity mediaTypeEnt ) throws MediaExc, MediaFailure { - //check first if the media file exist since produced - //location is also the storage location + /** {@inheritDoc} */ + public void store(UploadedFile anUploadedFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + try { + anUploadedFile.writeToFile(getStorageFile(aMedia, aMediaType)); - String date = ent.getFieldValue("date"); - String datePath = StringUtil.webdbDate2path(date); - String relPath = datePath+ent.getId()+"."+mediaTypeEnt.getFieldValue("name"); - String fname = getStoragePath()+relPath; - if(! new File(fname).exists()) - throw new MediaExc("error in MirMediaHandler.produce(): " + relPath + " does not exist!"); + aMedia.setFieldValue("publish_path", getRelativeStorageFile(aMedia, aMediaType)); + aMedia.setFieldValue("size", Long.toString(getStorageFile(aMedia, aMediaType).length())); + aMedia.update(); } - - public InputStream getMedia (Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure { - String publishPath = ent.getFieldValue("publish_path"); - String fname = getStoragePath()+publishPath; - File f = new File(fname); - if(! f.exists()) - throw new MediaExc("error in MirMediaHandler.getMedia(): " + fname + " does not exist!"); - - BufferedInputStream inputStream; - try { - inputStream = new BufferedInputStream(new FileInputStream(f)); - } - catch (Throwable e) { - throw new MediaFailure("MediaHandlerGeneric.getMedia(): " + e.toString(), e); - } - - return inputStream; + catch (Throwable e) { + logger.error("MediaHandlerGeneric.set: " + e.toString()); + throw new MediaFailure(e); } + } + + /** {@inheritDoc} */ + public void store(InputStream anInputStream, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + try { + FileFunctions.copy(anInputStream, getStorageFile(aMedia, aMediaType)); - public InputStream getThumbnail (Entity ent) throws MediaExc, MediaFailure { - return null; + aMedia.setFieldValue("publish_path", getRelativeStorageFile(aMedia, aMediaType)); + aMedia.setFieldValue("size", Long.toString(getStorageFile(aMedia, aMediaType).length())); + aMedia.update(); } + catch (Throwable e) { + logger.error("MediaHandlerGeneric.set: " + e.toString()); + throw new MediaFailure(e); + } + } + + public void produce(Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + if (!getStorageFile(aMedia, aMediaType).exists()) + throw new MediaExc("error in producing media:: " + getStorageFile(aMedia, aMediaType) + " does not exist!"); + } + + /** + * Get access to the raw media data by an {@link InputStream} + */ + public InputStream getMedia(Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + File file = getStorageFile(aMedia, aMediaType); + if (!file.exists()) + throw new MediaExc("error in MirMediaHandler.getMedia(): " + file + " does not exist!"); + + try { + return new BufferedInputStream(new FileInputStream(file)); + } + catch (Throwable e) { + throw new MediaFailure("MediaHandlerGeneric.getMedia(): " + e.toString(), e); + } + } - public String getThumbnailMimeType (Entity aMediaEntity, Entity aMediaType) throws MediaExc, MediaFailure { - ServletContext servletContext = MirPropertiesConfiguration.getContext(); - String fileName = aMediaEntity.getId()+"."+aMediaType.getFieldValue("name"); + public InputStream getThumbnail(Entity ent) throws MediaExc, MediaFailure { + return null; + } - return servletContext.getMimeType(fileName); - }; + public String getThumbnailMimeType(Entity aMediaEntity, Entity aMediaType) throws MediaExc, MediaFailure { + ServletContext servletContext = MirPropertiesConfiguration.getContext(); + String fileName = aMediaEntity.getId() + "." + aMediaType.getFieldValue("name"); - public String getStoragePath() - { - return configuration.getString("Producer.Media.Path"); - } + return servletContext.getMimeType(fileName); + }; - public String getIconStoragePath() - { - return configuration.getString("Producer.Image.IconPath"); - } + public String getStoragePath() { + return configuration.getString("Producer.Media.Path"); + } - public String getPublishHost() - { - return StringUtil.removeSlash(configuration.getString("Producer.Media.Host")); - } + public String getIconStoragePath() { + return configuration.getString("Producer.Image.IconPath"); + } - public String getTinyIconName() - { - return configuration.getString("Producer.Icon.TinyText"); - } + public String getPublishHost() { + return StringUtil.removeSlash(configuration.getString("Producer.Media.Host")); + } - public String getBigIconName() - { - return configuration.getString("Producer.Icon.BigText"); - } + public String getTinyIconName() { + return configuration.getString("Producer.Icon.TinyText"); + } - public String getIconAltName() - { - return "Generic media"; - } + public String getBigIconName() { + return configuration.getString("Producer.Icon.BigText"); + } - public List getURL(Entity ent, Entity mediaTypeEnt) - { - List theList = new Vector(); - theList.add(ent); - return theList; - } + public String getIconAltName() { + return "Generic media"; + } - public String getDescr( Entity mediaType) - { - return mediaType.getFieldValue("mime_type"); - } + public String getDescr(Entity mediaType) { + return mediaType.getFieldValue("mime_type"); + } } diff --git a/source/mircoders/media/MediaHandlerImages.java b/source/mircoders/media/MediaHandlerImages.java index 1e4f9fa9..9479315c 100755 --- a/source/mircoders/media/MediaHandlerImages.java +++ b/source/mircoders/media/MediaHandlerImages.java @@ -31,11 +31,13 @@ package mircoders.media; import java.io.File; import java.io.InputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.util.List; import java.util.Vector; +import java.util.ArrayList; import mir.config.MirPropertiesConfiguration; -import mir.config.MirPropertiesConfiguration.PropertiesConfigExc; import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.media.MediaExc; @@ -43,6 +45,8 @@ import mir.media.MediaFailure; import mir.media.MediaHandler; import mir.misc.FileUtil; import mir.misc.StringUtil; +import mir.session.UploadedFile; +import mir.session.SessionExc; import mircoders.entity.EntityImages; /** @@ -57,29 +61,19 @@ import mircoders.entity.EntityImages; * representation stuff (WebdbImage) happen here. * -mh 01.03.2002 * - * @see mir.media.MirMediaHandler + * @see mir.media.MediaHandler * @author mh - * @version $Id: MediaHandlerImages.java,v 1.23.2.4 2004/01/18 17:30:58 zapata Exp $ + * @version $Id: MediaHandlerImages.java,v 1.23.2.5 2004/11/21 22:07:14 zapata Exp $ */ -public abstract class MediaHandlerImages implements MediaHandler -{ - protected static MirPropertiesConfiguration configuration; +public abstract class MediaHandlerImages extends AbstractMediaHandler implements MediaHandler { + protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); protected static final String PNG = "PNG"; protected static final String JPEG = "JPEG"; protected LoggerWrapper logger; - static { - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new RuntimeException("Can't get configuration: " + e.getMessage()); - } - } - abstract String getType(); public MediaHandlerImages() { @@ -101,15 +95,32 @@ public abstract class MediaHandlerImages implements MediaHandler return inputStream; } - public void store(InputStream in, Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure { + public void store(UploadedFile anUploadedFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + try { + store(anUploadedFile.getInputStream(), aMedia, aMediaType); + } + catch (SessionExc e) { + throw new MediaFailure(e); + } + } + public void store(InputStream in, Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure { try { - ((EntityImages)ent).setImage(in, getType()); + ((EntityImages) ent).setImage(in, getType()); } catch (Throwable e) { - logger.error("MediaHandlerImages.set: "+e.getMessage()); - e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); + logger.error("MediaHandlerImages.store: "+e.toString()); + e.printStackTrace(logger.asPrintWriter(LoggerWrapper.ERROR_MESSAGE)); + throw new MediaExc("A problem has occurred processing the media file: " + e.toString()); + } + } + + public void store(File aFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + try { + store(new FileInputStream(aFile), aMedia, aMediaType); + } + catch (FileNotFoundException e) { throw new MediaFailure(e); } } @@ -128,7 +139,7 @@ public abstract class MediaHandlerImages implements MediaHandler ent.getFieldValue("image_data")!= null) { // make icon try { - InputStream in = ((EntityImages)ent).getIcon(); + InputStream in = ((EntityImages) ent).getIcon(); FileUtil.write(iconFilePath, in); in = ((EntityImages)ent).getImage(); FileUtil.write(productionFilePath, in); @@ -148,11 +159,10 @@ public abstract class MediaHandlerImages implements MediaHandler } } - public InputStream getThumbnail(Entity ent) throws MediaExc, MediaFailure { InputStream in; try { - in = ((EntityImages)ent).getIcon(); + in = ((EntityImages) ent).getIcon(); } catch (Throwable e) { logger.error("MediaHandlerImages.getIcon: " + e.toString()); @@ -162,13 +172,7 @@ public abstract class MediaHandlerImages implements MediaHandler return in; } - public List getURL(Entity ent, Entity mediaTypeEnt) { - List theList = new Vector(); - theList.add(ent); - return theList; - } - - public String getStoragePath() { + public String getStoragePath() { return configuration.getString("Producer.Image.Path"); } @@ -191,6 +195,7 @@ public abstract class MediaHandlerImages implements MediaHandler public String getIconAltName() { return "Image"; } + public String getDescr(Entity mediaType) { return "image/jpeg"; } diff --git a/source/mircoders/media/MediaHandlerImagesExtern.java b/source/mircoders/media/MediaHandlerImagesExtern.java index 7d90b7ff..c3a2a898 100755 --- a/source/mircoders/media/MediaHandlerImagesExtern.java +++ b/source/mircoders/media/MediaHandlerImagesExtern.java @@ -35,7 +35,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import mir.config.MirPropertiesConfiguration; import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.media.MediaExc; @@ -59,14 +58,6 @@ public class MediaHandlerImagesExtern extends MediaHandlerGeneric public MediaHandlerImagesExtern() { logger = new LoggerWrapper("Media.Images.Extern"); - try { - MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); - } - catch (Throwable t) { - logger.fatal("MediaHandlerImagesExtern: can't get configuration"); - - throw new RuntimeException(t.toString()); - } maxIconSize = configuration.getInt("Producer.Image.MaxIconSize"); minDescaleRatio = configuration.getFloat("Producer.Image.MinDescalePercentage")/100; @@ -115,22 +106,25 @@ public class MediaHandlerImagesExtern extends MediaHandlerGeneric } } catch(Throwable t) { - logger.error("MediaHandlerImagesExtern.produce: " + t.getMessage()); + logger.error("MediaHandlerImagesExtern.produce: " + t.toString()); t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); throw new MediaFailure(t.getMessage(), t); } } - public InputStream getIcon(Entity anImageEntity) throws MediaExc, MediaFailure { + /** {@inheritDoc} */ + public InputStream getThumbnail(Entity anImageEntity) throws MediaExc, MediaFailure { try { - String filePath = - configuration.getString("Producer.StorageRoot") + anImageEntity.getFieldValue("icon_path"); + File file = new File(configuration.getString("Producer.StorageRoot") + anImageEntity.getFieldValue("icon_path")); - logger.info(filePath); + if (!file.exists()) { + // hackish + file = new File(configuration.getHome(), "../img/photo_big.gif"); + } return new BufferedInputStream( - new FileInputStream(new File(filePath)),8192); + new FileInputStream(file),8192); } catch (Throwable t) { return null; diff --git a/source/mircoders/media/MediaHandlerImagesJpeg.java b/source/mircoders/media/MediaHandlerImagesJpeg.java index b6c23038..ec323990 100755 --- a/source/mircoders/media/MediaHandlerImagesJpeg.java +++ b/source/mircoders/media/MediaHandlerImagesJpeg.java @@ -39,10 +39,10 @@ import mir.media.MediaHandler; * It implements the MirMediaHandler interface. *

* - * @see mir.media.MirMediaHandler + * @see mir.media.MediaHandler * @see mircoders.media.MediaHandlerImages * @author mh, mir-coders group - * @version $Id: MediaHandlerImagesJpeg.java,v 1.6.2.1 2003/12/14 16:37:08 zapata Exp $ + * @version $Id: MediaHandlerImagesJpeg.java,v 1.6.2.2 2004/11/21 22:07:14 zapata Exp $ */ diff --git a/source/mircoders/media/MediaHandlerMp3.java b/source/mircoders/media/MediaHandlerMp3.java index ed968875..2deb304f 100755 --- a/source/mircoders/media/MediaHandlerMp3.java +++ b/source/mircoders/media/MediaHandlerMp3.java @@ -29,12 +29,6 @@ */ package mircoders.media; -import java.io.StringReader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.media.MediaExc; @@ -43,6 +37,8 @@ import mir.media.MediaHandler; import mir.misc.FileUtil; import mir.misc.StringUtil; +import java.io.StringReader; + /** * Please note: this media handler produces * 3 media files, the raw .mp3, a .m3u which is @@ -67,7 +63,7 @@ import mir.misc.StringUtil; * * @see mir.media.MediaHandler * @author mh - * @version $Id: MediaHandlerMp3.java,v 1.15.2.4 2004/01/18 17:30:59 zapata Exp $ + * @version $Id: MediaHandlerMp3.java,v 1.15.2.5 2004/11/21 22:07:14 zapata Exp $ */ public class MediaHandlerMp3 extends MediaHandlerAudio implements MediaHandler @@ -105,34 +101,6 @@ public class MediaHandlerMp3 extends MediaHandlerAudio implements MediaHandler } } - public List getURL(Entity ent, Entity mediaTypeEnt) { - List theList = new Vector(); - - //String stringSize = ent.getFieldValue("size"); - //int size = Integer.parseInt(stringSize, 10)/1024; - theList.add(ent); - - String basePath = StringUtil.regexpReplace(ent.getFieldValue("publish_path"), - ".mp3$", ""); - - // @todo the texts ("title") below urgently need to be sanely localizaeble - // somehow - Map m3uHash = new HashMap(); - m3uHash.put("publish_path", basePath + ".m3u"); - m3uHash.put("publish_server", ent.getFieldValue("publish_server")); - m3uHash.put("title", "stream URL"); - theList.add(m3uHash); - - Map plsHash = new HashMap(); - plsHash.put("publish_path", basePath + ".pls"); - plsHash.put("publish_server", ent.getFieldValue("publish_server")); - plsHash.put("title", "playlist URL"); - theList.add(plsHash); - - return theList; - - } - public String getDescr(Entity mediaType) { return "mp3"; } diff --git a/source/mircoders/media/MediaHandlerOgg.java b/source/mircoders/media/MediaHandlerOgg.java index d518f8b9..0e0a4573 100755 --- a/source/mircoders/media/MediaHandlerOgg.java +++ b/source/mircoders/media/MediaHandlerOgg.java @@ -106,35 +106,6 @@ public class MediaHandlerOgg extends MediaHandlerAudio implements MediaHandler } } - public List getURL(Entity ent, Entity mediaTypeEnt) { - List theList = new Vector(); - - //String stringSize = ent.getFieldValue("size"); - //int size = Integer.parseInt(stringSize, 10)/1024; - theList.add(ent); - - String basePath = StringUtil.regexpReplace(ent.getFieldValue("publish_path"), - ".ogg$", ""); - - // @todo the texts ("title") below urgently need to be sanely localizaeble - // somehow - //no .m3u! - //Map m3uHash = new HashMap(); - //m3uHash.put("publish_path", basePath + ".m3u"); - //m3uHash.put("publish_server", ent.getFieldValue("publish_server")); - //m3uHash.put("title", "stream URL"); - //theList.add(m3uHash); - - Map plsHash = new HashMap(); - plsHash.put("publish_path", basePath + ".pls"); - plsHash.put("publish_server", ent.getFieldValue("publish_server")); - plsHash.put("title", "playlist URL"); - theList.add(plsHash); - - return theList; - - } - public String getDescr(Entity mediaType) { return "ogg"; } diff --git a/source/mircoders/media/MediaHandlerRealAudio.java b/source/mircoders/media/MediaHandlerRealAudio.java index 7e0ce648..3cbeb211 100755 --- a/source/mircoders/media/MediaHandlerRealAudio.java +++ b/source/mircoders/media/MediaHandlerRealAudio.java @@ -53,7 +53,7 @@ import mir.misc.StringUtil; * @see mir.media.MediaHandlerGeneric * @see mir.media.MediaHandler * @author john , mh - * @version $Id: MediaHandlerRealAudio.java,v 1.19.2.4 2004/01/18 17:30:59 zapata Exp $ + * @version $Id: MediaHandlerRealAudio.java,v 1.19.2.5 2004/11/21 22:07:14 zapata Exp $ */ @@ -87,28 +87,6 @@ public class MediaHandlerRealAudio extends MediaHandlerAudio implements MediaHan } } - public List getURL(Entity ent, Entity mediaTypeEnt) - { - List theList = new Vector(); - - //String stringSize = ent.getFieldValue("size"); - //int size = Integer.parseInt(stringSize, 10)/1024; - theList.add(ent); - - String basePath=StringUtil.regexpReplace(ent.getFieldValue("publish_path"), - ".ra$",""); - - // @todo the texts ("title") below urgently need to be sanely localizaeble - // somehow - Map ramHash = new HashMap(); - ramHash.put("publish_path", basePath+".ram"); - ramHash.put("publish_server", configuration.getString("Producer.Media.Host")); - ramHash.put("title", "stream URL"); - theList.add(ramHash); - - return theList; - } - public String getStoragePath() { return configuration.getString("Producer.RealMedia.Path"); diff --git a/source/mircoders/media/MediaHandlerRealVideo.java b/source/mircoders/media/MediaHandlerRealVideo.java index 849461c8..0807c39e 100755 --- a/source/mircoders/media/MediaHandlerRealVideo.java +++ b/source/mircoders/media/MediaHandlerRealVideo.java @@ -29,13 +29,6 @@ */ package mircoders.media; -import java.io.File; -import java.io.StringReader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.media.MediaExc; @@ -44,6 +37,9 @@ import mir.media.MediaHandler; import mir.misc.FileUtil; import mir.misc.StringUtil; +import java.io.File; +import java.io.StringReader; + /** @@ -51,10 +47,9 @@ import mir.misc.StringUtil; * * 03.2002 - reworked Realmedia handling. -mh * - * @see mir.media.MediaHandlerGeneric * @see mir.media.MediaHandler * @author john , mh - * @version $Id: MediaHandlerRealVideo.java,v 1.19.2.4 2004/01/18 17:30:59 zapata Exp $ + * @version $Id: MediaHandlerRealVideo.java,v 1.19.2.5 2004/11/21 22:07:14 zapata Exp $ */ @@ -89,28 +84,6 @@ public class MediaHandlerRealVideo extends MediaHandlerVideo implements MediaHan } } - public List getURL(Entity ent, Entity mediaTypeEnt) { - List theList = new Vector(); - - //String stringSize = ent.getFieldValue("size"); - //int size = Integer.parseInt(stringSize, 10)/1024; - theList.add(ent); - - String basePath=StringUtil.regexpReplace(ent.getFieldValue("publish_path"), - ".rm$",""); - - // @todo the texts ("title") below urgently need to be sanely localizaeble - // somehow - Map ramHash = new HashMap(); - ramHash.put("publish_path", basePath+".ram"); - ramHash.put("publish_server", configuration.getString("Producer.Media.Host")); - ramHash.put("title", "stream URL"); - theList.add(ramHash); - - return theList; - - } - public String getStoragePath() { return configuration.getString("Producer.RealMedia.Path"); } diff --git a/source/mircoders/media/MediaHandlerVideo.java b/source/mircoders/media/MediaHandlerVideo.java index c5830a1a..4ba84d3d 100755 --- a/source/mircoders/media/MediaHandlerVideo.java +++ b/source/mircoders/media/MediaHandlerVideo.java @@ -40,7 +40,7 @@ import mir.media.MediaHandler; * @see mir.media.MediaHandlerGeneric * @see mir.media.MediaHandler * @author john - * @version $Id: MediaHandlerVideo.java,v 1.9.2.1 2003/12/14 16:37:08 zapata Exp $ + * @version $Id: MediaHandlerVideo.java,v 1.9.2.2 2004/11/21 22:07:14 zapata Exp $ */ public class MediaHandlerVideo extends MediaHandlerGeneric implements MediaHandler @@ -53,7 +53,7 @@ public class MediaHandlerVideo extends MediaHandlerGeneric implements MediaHandl bigIcon = configuration.getString("Producer.Icon.BigVideo"); } - public String getTinyIcon() { + public String getTinyIconName() { return tinyIcon; } @@ -61,7 +61,7 @@ public class MediaHandlerVideo extends MediaHandlerGeneric implements MediaHandl return bigIcon; } - public String getIconAlt() { + public String getIconAltName() { return "Video"; } diff --git a/source/mircoders/media/MediaUploadProcessor.java b/source/mircoders/media/MediaUploadProcessor.java index f423ddf8..8825e899 100755 --- a/source/mircoders/media/MediaUploadProcessor.java +++ b/source/mircoders/media/MediaUploadProcessor.java @@ -29,81 +29,83 @@ */ package mircoders.media; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Map; - import mir.entity.Entity; -import mir.media.MediaExc; +import mir.log.LoggerWrapper; import mir.media.MediaFailure; -import mircoders.media.MediaHelper; import mir.media.MediaHandler; import mir.misc.StringUtil; import mir.session.UploadedFile; import mir.storage.Database; +import mir.util.FileFunctions; import mircoders.module.ModuleMediaType; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + public class MediaUploadProcessor { - public static Entity processMediaUpload(UploadedFile aFile, Map aValues) throws MediaExc, MediaFailure { - String mediaId; + private static LoggerWrapper logger = new LoggerWrapper("Media.UploadProcessor"); + private static ModuleMediaType mediaTypeModule = new ModuleMediaType(); + + /** + * Processes an uploaded media file. + * Will create the media entity and so on. + */ + public static Entity processMediaUpload(UploadedFile aFile, Map aValues) throws UnsupportedMediaTypeExc, MediaFailure { MediaHandler mediaHandler; - Entity mediaType; - ModuleMediaType mediaTypeModule; + Entity mediaType = null; Database mediaStorage; Map values = new HashMap(); - String MediaId; Entity mediaEntity; + String contentType = aFile.getContentType(); + logger.debug("processing media upload of " + aFile.getFileName() + " (content type = " + contentType + ")"); - try { - String contentType = aFile.getContentType(); - - if (contentType.equals("text/plain") || - contentType.equals("application/octet-stream") || - contentType == null) { - throw new MediaExc("Invalid content-type: " + contentType); - } - - values.putAll(aValues); - values.put("date", StringUtil.date2webdbDate(new GregorianCalendar())); - values.put("is_produced", "0"); - - mediaTypeModule = new ModuleMediaType(); + if (contentType!=null) { mediaType = mediaTypeModule.findMediaTypeForMimeType(contentType); + } - try { - mediaHandler = MediaHelper.getHandler(mediaType); - mediaStorage = MediaHelper.getStorage(mediaType, mediaType.getFieldValue("tablename")); - } - catch (Throwable e) { - throw new MediaFailure(e); - } + if (mediaType==null) { + String extension = FileFunctions.getExtension(aFile.getFileName()); + mediaType = mediaTypeModule.findMediaTypeForExtension(extension); + } + + if (mediaType==null) { + throw new UnsupportedMediaTypeExc("Media " + aFile.getFileName() + " " + + (aFile!=null?"("+aFile.getContentType()+") ":"") + " not supported", aFile.getContentType()); + } - values.put("to_media_type", mediaType.getId()); + values.putAll(aValues); + values.put("date", StringUtil.date2webdbDate(new GregorianCalendar())); + values.put("is_produced", "0"); - try { - mediaEntity = (Entity) mediaStorage.getEntityClass().newInstance(); - mediaEntity.setStorage(mediaStorage); - } - catch (Throwable e) { - throw new MediaFailure(e); - } + try { + mediaHandler = MediaHelper.getHandler(mediaType); + mediaStorage = MediaHelper.getStorage(mediaType, mediaType.getFieldValue("tablename")); + } + catch (Throwable e) { + throw new MediaFailure(e); + } - mediaEntity.setFieldValues(values); - mediaId = mediaEntity.insert(); + values.put("to_media_type", mediaType.getId()); - try { - mediaHandler.store(aFile.getInputStream(), mediaEntity, mediaType); - } - catch (Throwable e) { - throw new MediaFailure(e); - } + try { + mediaEntity = (Entity) mediaStorage.getEntityClass().newInstance(); + mediaEntity.setStorage(mediaStorage); + } + catch (Throwable e) { + throw new MediaFailure(e); + } - return mediaEntity; + mediaEntity.setFieldValues(values); + try { + mediaEntity.insert(); + mediaHandler.store(aFile, mediaEntity, mediaType); } catch (Throwable e) { throw new MediaFailure(e); } + return mediaEntity; } } \ No newline at end of file diff --git a/source/mircoders/media/URLMediaHandler.java b/source/mircoders/media/URLMediaHandler.java index 6603d1c9..8401074a 100755 --- a/source/mircoders/media/URLMediaHandler.java +++ b/source/mircoders/media/URLMediaHandler.java @@ -1,15 +1,19 @@ package mircoders.media; -import mir.media.*; +import mir.entity.Entity; +import mir.media.MediaExc; +import mir.media.MediaFailure; +import mir.media.MediaHandler; +import mir.session.UploadedFile; + +import java.io.File; import java.io.InputStream; -import mir.entity.*; -import java.util.List; -import java.util.ArrayList; /** *

URLMediaHandler

*

Description: - * This is a media handler for media that are only known by url. + * This is a media handler for externally stored media. + * The media is presented by its url. *

* @author Zapata */ @@ -25,11 +29,41 @@ public class URLMediaHandler implements MediaHandler { iconAlternative = anIconAlternative; } + /** + * {@inheritDoc} + * + * Since this media handler assumes the media is stored on a wholly different + * server, this operation is not applicable + */ + public void store(UploadedFile anUploadedFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + * + * Since this media handler assumes the media is stored on a wholly different + * server, this operation is not applicable + */ public void store(InputStream anInputStream, Entity anEntity, Entity aMediaTypeEntity) throws MediaExc, MediaFailure { throw new UnsupportedOperationException(); - }; + } + + /** + * {@inheritDoc} + * + * Since this media handler assumes the media is stored on a wholly different + * server, this operation is not applicable + */ + public void store(File aFile, Entity aMedia, Entity aMediaType) throws MediaExc, MediaFailure { + throw new UnsupportedOperationException(); + } + /** + * {@inheritDoc} + */ public void produce(Entity anEntity, Entity aMediaTypeEntity) throws MediaExc, MediaFailure { + // nothing to do here } public InputStream getMedia(Entity anEntity, Entity aMediaTypeEntity) throws MediaExc, MediaFailure { @@ -44,17 +78,6 @@ public class URLMediaHandler implements MediaHandler { return "application/octetstream"; } - public List getURL(Entity aMediaEntity, Entity aMediaTypeEntity) throws MediaExc, MediaFailure { - List result = new ArrayList(); - result.add(aMediaTypeEntity.getFieldValue("publish_server")+aMediaTypeEntity.getFieldValue("publish_path")); - - return result; - } - - public Object getURLs(Entity ent, Entity mediaTypeEnt) throws MediaExc, MediaFailure { - return null; - } - public String getStoragePath () throws MediaExc, MediaFailure { throw new UnsupportedOperationException(); } @@ -79,7 +102,7 @@ public class URLMediaHandler implements MediaHandler { return iconAlternative; } - public String getDescr (Entity mediaTypeEnt) { + public String getDescr(Entity mediaTypeEnt) { return "Url"; } } \ No newline at end of file diff --git a/source/mircoders/media/UnsupportedMediaTypeExc.java b/source/mircoders/media/UnsupportedMediaTypeExc.java new file mode 100755 index 00000000..e0320504 --- /dev/null +++ b/source/mircoders/media/UnsupportedMediaTypeExc.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.media; + +import multex.Exc; + +public class UnsupportedMediaTypeExc extends Exc { + private String mimeType; + + public UnsupportedMediaTypeExc(String aMessage, String aMimeType) { + super(aMessage); + mimeType = aMimeType; + } + + public String getMimeType() { + return mimeType; + } +} diff --git a/source/mircoders/module/ModuleArticleType.java b/source/mircoders/module/ModuleArticleType.java index 8a127675..953a732f 100755 --- a/source/mircoders/module/ModuleArticleType.java +++ b/source/mircoders/module/ModuleArticleType.java @@ -33,18 +33,14 @@ import mir.log.LoggerWrapper; import mir.module.AbstractModule; import mir.module.ModuleExc; import mir.module.ModuleFailure; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; +import mircoders.storage.DatabaseArticleType; public class ModuleArticleType extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.ArticleType"); - public ModuleArticleType (StorageObject theStorage) { - - if (theStorage == null) - logger.warn("ModuleArticleType -- StorageObject was null!"); - - this.storage = theStorage; + public ModuleArticleType() { + super(DatabaseArticleType.getInstance()); } public String articleTypeIdForName(String aName) throws ModuleExc, ModuleFailure { diff --git a/source/mircoders/module/ModuleBreaking.java b/source/mircoders/module/ModuleBreaking.java index 16dba4c2..7c0e6d27 100755 --- a/source/mircoders/module/ModuleBreaking.java +++ b/source/mircoders/module/ModuleBreaking.java @@ -31,7 +31,7 @@ package mircoders.module; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.storage.StorageObject; +import mircoders.storage.DatabaseBreaking; @@ -46,11 +46,8 @@ public class ModuleBreaking extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Breaking"); - public ModuleBreaking (StorageObject theStorage) + public ModuleBreaking () { - if (theStorage == null) logger.warn("ModuleBreaking -- StorageObject was null!"); - this.storage = theStorage; + super (DatabaseBreaking.getInstance()); } - -// Methoden } diff --git a/source/mircoders/module/ModuleComment.java b/source/mircoders/module/ModuleComment.java index 853eb25a..a66d4ccc 100755 --- a/source/mircoders/module/ModuleComment.java +++ b/source/mircoders/module/ModuleComment.java @@ -29,16 +29,16 @@ */ package mircoders.module; -import java.util.Map; - import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.module.AbstractModule; import mir.module.ModuleExc; import mir.module.ModuleFailure; -import mir.storage.StorageObject; +import mircoders.storage.DatabaseComment; import mircoders.storage.DatabaseContent; +import java.util.Map; + /* * ModuleComment - methods and access for comments @@ -50,10 +50,9 @@ public class ModuleComment extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Comment"); - public ModuleComment(StorageObject theStorage) + public ModuleComment() { - if (theStorage == null) logger.warn("StorageObject was null!"); - this.storage = theStorage; + super(DatabaseComment.getInstance()); } public void deleteById (String anId) throws ModuleExc, ModuleFailure { diff --git a/source/mircoders/module/ModuleCommentStatus.java b/source/mircoders/module/ModuleCommentStatus.java index f0d9a987..8a9417d2 100755 --- a/source/mircoders/module/ModuleCommentStatus.java +++ b/source/mircoders/module/ModuleCommentStatus.java @@ -33,17 +33,14 @@ import mir.log.LoggerWrapper; import mir.module.AbstractModule; import mir.module.ModuleExc; import mir.module.ModuleFailure; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; +import mircoders.storage.DatabaseCommentStatus; public class ModuleCommentStatus extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.CommentStatus"); - public ModuleCommentStatus (StorageObject theStorage) { - if (theStorage == null) - logger.warn("ModuleCommentStatus -- StorageObject was null!"); - - this.storage = theStorage; + public ModuleCommentStatus () { + super(DatabaseCommentStatus.getInstance()); } public String commentStatusIdForName(String aName) throws ModuleExc, ModuleFailure { diff --git a/source/mircoders/module/ModuleContent.java b/source/mircoders/module/ModuleContent.java index 7ba90822..d3877d5c 100755 --- a/source/mircoders/module/ModuleContent.java +++ b/source/mircoders/module/ModuleContent.java @@ -32,9 +32,9 @@ package mircoders.module; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; -import mircoders.global.*; +import mircoders.global.MirGlobal; +import mircoders.storage.DatabaseContent; /** * @@ -51,11 +51,7 @@ public class ModuleContent extends AbstractModule static LoggerWrapper logger = new LoggerWrapper("Module.Content"); public ModuleContent() { - super(); - } - - public ModuleContent(StorageObject aStorage) { - storage = aStorage; + super(DatabaseContent.getInstance()); } public void expireArticleLock(String anId, String aUserId) { diff --git a/source/mircoders/module/ModuleImages.java b/source/mircoders/module/ModuleImages.java index eaef33fd..f6214484 100755 --- a/source/mircoders/module/ModuleImages.java +++ b/source/mircoders/module/ModuleImages.java @@ -31,14 +31,12 @@ package mircoders.module; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.storage.StorageObject; +import mircoders.storage.DatabaseImages; public class ModuleImages extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Images"); - public ModuleImages(StorageObject theStorage) { - if (theStorage == null) - logger.warn("ModuleImages: StorageObject was null!"); - this.storage = theStorage; + public ModuleImages() { + super(DatabaseImages.getInstance()); } } diff --git a/source/mircoders/module/ModuleLanguage.java b/source/mircoders/module/ModuleLanguage.java index e33de75f..565d3d97 100755 --- a/source/mircoders/module/ModuleLanguage.java +++ b/source/mircoders/module/ModuleLanguage.java @@ -33,8 +33,10 @@ import mir.log.LoggerWrapper; import mir.module.AbstractModule; import mir.module.ModuleExc; import mir.module.ModuleFailure; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; +import mir.entity.Entity; +import mir.entity.EntityList; +import mircoders.storage.DatabaseLanguage; /** * Title: mir - another content management system @@ -48,11 +50,8 @@ import mir.util.JDBCStringRoutines; public class ModuleLanguage extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Language"); - public ModuleLanguage (StorageObject theStorage) { - if (theStorage == null) - logger.warn("ModuleLanguage -- StorageObject was null!"); - - this.storage = theStorage; + public ModuleLanguage () { + super(DatabaseLanguage.getInstance()); } public String languageIdForCode(String aCode) throws ModuleExc, ModuleFailure { @@ -63,4 +62,19 @@ public class ModuleLanguage extends AbstractModule { throw new ModuleFailure(t); } } + + public Entity languageForCode(String aCode) throws ModuleExc, ModuleFailure { + try { + EntityList list = storage.selectByFieldValue("code", aCode); + if (list.size()>0) { + return list.elementAt(0); + } + else { + throw new ModuleExc("No language found for code " + aCode); + } + } + catch (Throwable t) { + throw new ModuleFailure(t); + } + } } \ No newline at end of file diff --git a/source/mircoders/module/ModuleMediaType.java b/source/mircoders/module/ModuleMediaType.java index 8a75c378..19850a53 100755 --- a/source/mircoders/module/ModuleMediaType.java +++ b/source/mircoders/module/ModuleMediaType.java @@ -30,35 +30,28 @@ package mircoders.module; -import java.util.List; - import mir.entity.Entity; import mir.entity.EntityList; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.module.ModuleExc; -import mir.module.ModuleFailure; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; import mir.util.StringRoutines; import mircoders.storage.DatabaseMediaType; +import java.util.List; + public class ModuleMediaType extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Content"); public ModuleMediaType() { - this (DatabaseMediaType.getInstance()); + super(DatabaseMediaType.getInstance()); } - public ModuleMediaType(StorageObject aStorage) { - this.storage = aStorage; - } - - public Entity findMediaTypeForMimeType(String aMimeType) throws ModuleExc, ModuleFailure { + public Entity findMediaTypeForMimeType(String aMimeType) { List contentTypeParts = StringRoutines.splitString(aMimeType, "/"); if (contentTypeParts.size()!=2) { - throw new InvalidMimeTypeExc("Invalid mimetype: " + aMimeType, aMimeType); + return null; } String mimeTypeMajor = (String) contentTypeParts.get(0); @@ -69,34 +62,20 @@ public class ModuleMediaType extends AbstractModule { mediaTypes = DatabaseMediaType.getInstance().selectByWhereClause("mime_type = '"+JDBCStringRoutines.escapeStringLiteral(mimeTypeMajor+"/*")+"'"); } if (mediaTypes.size() == 0) { - throw new UnsupportedMimeTypeExc("Unsupported mimetype: " + aMimeType, aMimeType); + return null; } return (Entity) mediaTypes.elementAt(0); } - public static class MimeTypeExc extends ModuleExc { - private String mimeType; - - public MimeTypeExc(String aMessage, String aMimeType) { - super (aMessage); - mimeType = aMimeType; - } - - public String getMimeType() { - return mimeType; - } - } + public Entity findMediaTypeForExtension(String anExtension) { + EntityList mediaTypes = DatabaseMediaType.getInstance().selectByWhereClause("name = '"+JDBCStringRoutines.escapeStringLiteral(anExtension)+"'"); - public static class UnsupportedMimeTypeExc extends MimeTypeExc { - public UnsupportedMimeTypeExc(String aMessage, String aMimeType) { - super(aMessage, aMimeType); + if (mediaTypes.size() == 0) { + return null; } - } - - public static class InvalidMimeTypeExc extends MimeTypeExc { - public InvalidMimeTypeExc(String aMessage, String aMimeType) { - super(aMessage, aMimeType); + else { + return (Entity) mediaTypes.elementAt(0); } } } \ No newline at end of file diff --git a/source/mircoders/module/ModuleMediafolder.java b/source/mircoders/module/ModuleMediafolder.java index fe97a7e3..0dfb7ded 100755 --- a/source/mircoders/module/ModuleMediafolder.java +++ b/source/mircoders/module/ModuleMediafolder.java @@ -44,19 +44,15 @@ import mir.module.ModuleExc; import mir.module.ModuleFailure; import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; +import mircoders.storage.DatabaseMediafolder; - -public class ModuleMediafolder extends AbstractModule -{ +public class ModuleMediafolder extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Mediafolder"); - public ModuleMediafolder(StorageObject aStorage) - { - if (aStorage == null) - logger.warn("ModuleMediafolder: StorageObject was null!"); - - storage = aStorage; + public ModuleMediafolder() { + super(DatabaseMediafolder.getInstance()); } + public String mediaFolderIdForName(String aName) throws ModuleExc, ModuleFailure { try { return storage.executeFreeSingleValueSql("select id from media_folder where name = '" + JDBCStringRoutines.escapeStringLiteral(aName) + "'"); diff --git a/source/mircoders/module/ModuleMessage.java b/source/mircoders/module/ModuleMessage.java index 79def2bb..18fdcd3b 100755 --- a/source/mircoders/module/ModuleMessage.java +++ b/source/mircoders/module/ModuleMessage.java @@ -31,26 +31,12 @@ package mircoders.module; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.storage.StorageObject; +import mircoders.storage.DatabaseMessages; -/** - * Title: ModuleMessage - * Description: - * Copyright: Copyright (c) 2001 - * Company: Indymedia - * @author - * @version 1.0 - */ - - -public class ModuleMessage extends AbstractModule -{ +public class ModuleMessage extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Message"); - public ModuleMessage (StorageObject theStorage) - { - if (theStorage == null) logger.warn("ModuleMessage -- StorageObject was null!"); - - this.storage = theStorage; + public ModuleMessage () { + super(DatabaseMessages.getInstance()); } } \ No newline at end of file diff --git a/source/mircoders/module/ModuleTopics.java b/source/mircoders/module/ModuleTopics.java index f2351340..9cc517c0 100755 --- a/source/mircoders/module/ModuleTopics.java +++ b/source/mircoders/module/ModuleTopics.java @@ -29,44 +29,15 @@ */ package mircoders.module; -import java.util.Map; - -import mir.entity.Entity; import mir.log.LoggerWrapper; import mir.module.AbstractModule; -import mir.module.ModuleExc; -import mir.module.ModuleFailure; -import mir.storage.StorageObject; +import mircoders.storage.DatabaseTopics; public class ModuleTopics extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Topics"); - public ModuleTopics(StorageObject theStorage) { - this.storage = theStorage; + public ModuleTopics() { + super (DatabaseTopics.getInstance()); } - - /** - * Overrides the AbstractModule.set(), - * All dependent ContentEntities are set unproduced. - * - * @param theValues Hash mit Spalte/Wert-Paaren - * @return Id des eingef?gten Objekts - */ - public String set(Map theValues) throws ModuleExc, ModuleFailure { - try { - Entity theEntity = storage.selectById((String) theValues.get("id")); - if (theEntity == null) { - throw new ModuleExc("No topic with id " + theValues.get("id") + " found"); - } - theEntity.setFieldValues(theValues); - theEntity.update(); - - return theEntity.getId(); - } - catch (Throwable e) { - throw new ModuleFailure(e); - } - } - } diff --git a/source/mircoders/module/ModuleUploadedMedia.java b/source/mircoders/module/ModuleUploadedMedia.java index 8eaf59f3..49cc431a 100755 --- a/source/mircoders/module/ModuleUploadedMedia.java +++ b/source/mircoders/module/ModuleUploadedMedia.java @@ -49,6 +49,6 @@ public class ModuleUploadedMedia extends AbstractModule static LoggerWrapper logger = new LoggerWrapper("Module.UploadedMedia"); public ModuleUploadedMedia(StorageObject aStorage) { - storage = aStorage; + super(aStorage); } } \ No newline at end of file diff --git a/source/mircoders/module/ModuleUsers.java b/source/mircoders/module/ModuleUsers.java index eaf4ff08..259cb452 100755 --- a/source/mircoders/module/ModuleUsers.java +++ b/source/mircoders/module/ModuleUsers.java @@ -30,18 +30,18 @@ package mircoders.module; -import java.util.HashMap; -import java.util.Map; - import mir.entity.EntityList; import mir.log.LoggerWrapper; import mir.module.AbstractModule; import mir.module.ModuleExc; import mir.module.ModuleFailure; -import mir.storage.StorageObject; import mir.util.JDBCStringRoutines; import mircoders.entity.EntityUsers; import mircoders.global.MirGlobal; +import mircoders.storage.DatabaseUsers; + +import java.util.HashMap; +import java.util.Map; /* @@ -55,12 +55,8 @@ public class ModuleUsers extends AbstractModule { static LoggerWrapper logger = new LoggerWrapper("Module.Users"); - public ModuleUsers(StorageObject aStorage) - { - if (aStorage == null) - logger.warn("ModuleUsers(): StorageObject was null!"); - - storage = aStorage; + public ModuleUsers() { + super(DatabaseUsers.getInstance()); } /** @@ -108,7 +104,7 @@ public class ModuleUsers extends AbstractModule } } - private Map digestPassword(Map aValues) throws ModuleExc, ModuleFailure { + private Map digestPassword(Map aValues) throws ModuleFailure { Map result = aValues; try { diff --git a/source/mircoders/pdf/PDFGenerator.java b/source/mircoders/pdf/PDFGenerator.java index 3676ddb4..4cc74c22 100755 --- a/source/mircoders/pdf/PDFGenerator.java +++ b/source/mircoders/pdf/PDFGenerator.java @@ -118,12 +118,7 @@ public class PDFGenerator{ public PDFGenerator(ByteArrayOutputStream out){ logger = new LoggerWrapper("PDFGenerator"); - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (MirPropertiesConfiguration.PropertiesConfigExc e) { - throw new RuntimeException("Can't get configuration: " + e.getMessage()); - } + configuration = MirPropertiesConfiguration.instance(); localImageDir=configuration.getString("Producer.Image.Path"); try { diff --git a/source/mircoders/producer/ContentModifyingProducerNode.java b/source/mircoders/producer/ContentModifyingProducerNode.java index 787923e1..3aa63d11 100755 --- a/source/mircoders/producer/ContentModifyingProducerNode.java +++ b/source/mircoders/producer/ContentModifyingProducerNode.java @@ -38,9 +38,6 @@ import mir.producer.ProducerFailure; import mir.producer.ProducerNode; import mir.util.ParameterExpander; import mircoders.entity.EntityContent; -import mircoders.module.ModuleContent; -import mircoders.storage.DatabaseContent; - public class ContentModifyingProducerNode implements ProducerNode { private String contentKey; @@ -60,8 +57,6 @@ public class ContentModifyingProducerNode implements ProducerNode { String fieldName; try { - ModuleContent contentModule = new ModuleContent(DatabaseContent.getInstance()); - data = ParameterExpander.findValueForKey( aValueMap, contentKey ); if (! (data instanceof EntityAdapter)) { diff --git a/source/mircoders/producer/IndexingProducerNode.java b/source/mircoders/producer/IndexingProducerNode.java index 685a2c15..db12ed70 100755 --- a/source/mircoders/producer/IndexingProducerNode.java +++ b/source/mircoders/producer/IndexingProducerNode.java @@ -34,6 +34,7 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Map; +import java.io.File; import mir.entity.Entity; import mir.entity.adapter.EntityAdapter; @@ -42,6 +43,7 @@ import mir.misc.StringUtil; import mir.producer.ProducerFailure; import mir.producer.ProducerNode; import mir.util.ParameterExpander; +import mir.util.FileFunctions; import mircoders.entity.EntityContent; import mircoders.search.AudioSearchTerm; import mircoders.search.ContentSearchTerm; @@ -63,10 +65,12 @@ import org.apache.lucene.store.FSDirectory; public class IndexingProducerNode implements ProducerNode { private String contentKey; private String indexPath; + private File indexBasePath; - public IndexingProducerNode(String aContentKey, String pathToIndex) { + public IndexingProducerNode(File anIndexBasePath, String aContentKey, String pathToIndex) { contentKey = aContentKey; indexPath = pathToIndex; + indexBasePath = anIndexBasePath; } public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) @@ -74,14 +78,14 @@ public class IndexingProducerNode implements ProducerNode { IndexWriter indexWriter = null; Object data; Entity entity; - String index = null; long startTime; long endTime; + File indexFile = null; startTime = System.currentTimeMillis(); try { - index = ParameterExpander.expandExpression(aValueMap, indexPath); + indexFile = FileFunctions.getAbsoluteOrRelativeFile(indexBasePath, ParameterExpander.expandExpression(aValueMap, indexPath)); data = ParameterExpander.findValueForKey(aValueMap, contentKey); if (!(data instanceof EntityAdapter)) { @@ -98,22 +102,19 @@ public class IndexingProducerNode implements ProducerNode { entity.getClass().getName() + " adapter", null); } - aLogger.info("Indexing " + (String) entity.getFieldValue("id") + " into " + - index); + aLogger.info("Indexing " + entity.getFieldValue("id") + " into " + indexFile.getAbsolutePath()); // create an index here if one did not already exist - if (!(IndexReader.indexExists(index))) { - aLogger.error("Didn't find existing index, so I'm making one in " + - index); + if (!(IndexReader.indexExists(indexFile))) { + aLogger.error("Didn't find existing index, so I'm making one in " + indexFile.getAbsolutePath()); - IndexWriter indexCreator = - new IndexWriter(index, new StandardAnalyzer(), true); + IndexWriter indexCreator = new IndexWriter(indexFile, new StandardAnalyzer(), true); indexCreator.close(); } - IndexUtil.unindexEntity((EntityContent) entity, index); + IndexUtil.unindexEntity((EntityContent) entity, indexFile); - indexWriter = new IndexWriter(index, new StandardAnalyzer(), false); + indexWriter = new IndexWriter(indexFile, new StandardAnalyzer(), false); Document theDoc = new Document(); @@ -136,21 +137,21 @@ public class IndexingProducerNode implements ProducerNode { if (textValue!=null) { try { - year = Integer.parseInt(textValue.substring(0,4)); - month = Integer.parseInt(textValue.substring(5,7)); - day = Integer.parseInt(textValue.substring(8,10)); - hours = Integer.parseInt(textValue.substring(11,13)); - minutes = Integer.parseInt(textValue.substring(14,16)); + year = Integer.parseInt(textValue.substring(0, 4)); + month = Integer.parseInt(textValue.substring(5, 7)); + day = Integer.parseInt(textValue.substring(8, 10)); + hours = Integer.parseInt(textValue.substring(11, 13)); + minutes = Integer.parseInt(textValue.substring(14, 16)); - calendar.set(year, month-1, day, hours, minutes); + calendar.set(year, month - 1, day, hours, minutes); date = calendar.getTime(); - SimpleDateFormat formatter = new SimpleDateFormat ("yyyy.MM.dd hh:mm"); - formattedDate=formatter.format(date); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd hh:mm"); + formattedDate = formatter.format(date); + } + catch (Throwable t) { + aLogger.error("Error while generating content date to index: " + t.getMessage()); + t.printStackTrace(aLogger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); } - catch (Throwable t){ - aLogger.error("Error while generating content date to index: " + t.getMessage()); - t.printStackTrace(aLogger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); - } } (new KeywordSearchTerm("webdb_create_formatted", "search_date", "webdb_create_formatted", "webdb_create_formatted", @@ -205,19 +206,23 @@ public class IndexingProducerNode implements ProducerNode { if (indexWriter != null) { try { indexWriter.close(); - } catch (Throwable t) { + } + catch (Throwable t) { aLogger.warn("Error while closing indexWriter: " + t.getMessage()); } } - try { - FSDirectory theIndexDir = FSDirectory.getDirectory(index, false); + if (indexFile!=null) { + try { + FSDirectory theIndexDir = FSDirectory.getDirectory(indexFile, false); - if (IndexReader.isLocked(theIndexDir)) { - IndexReader.unlock(theIndexDir); + if (IndexReader.isLocked(theIndexDir)) { + IndexReader.unlock(theIndexDir); + } + } + catch (Throwable t) { + aLogger.warn("Error while unlocking index: " + t.getMessage()); } - } catch (Throwable t) { - aLogger.warn("Error while unlocking index: " + t.getMessage()); } } diff --git a/source/mircoders/producer/RadicalendarProducerNode.java b/source/mircoders/producer/RadicalendarProducerNode.java new file mode 100755 index 00000000..c01fab33 --- /dev/null +++ b/source/mircoders/producer/RadicalendarProducerNode.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mircoders.producer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +import mir.log.LoggerWrapper; +import mir.producer.ProducerFailure; +import mir.producer.ProducerNode; +import mir.util.ExceptionFunctions; +import mir.util.ParameterExpander; + +import org.apache.xmlrpc.XmlRpcClient; +import org.apache.xmlrpc.XmlRpcException; + + +public class RadicalendarProducerNode implements ProducerNode { + private String key; + private String groupname; + private String gmtoffset; + + + public RadicalendarProducerNode(String aKey, String aGroupName, String aGMTOffset) { + key = aKey; + groupname = aGroupName; + gmtoffset = aGMTOffset; + + } + + public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { + try { + String expandedGroupName = ParameterExpander.expandExpression( aValueMap, groupname); + String expandedGMTOffset = ParameterExpander.expandExpression( aValueMap, gmtoffset); + + HashMap events=new HashMap(); + + XmlRpcClient xmlrpc = new XmlRpcClient ("http://radicalendar.org:80/xmlresponderweek.php"); + Vector params = new Vector (); + params.addElement(expandedGroupName+":"+expandedGMTOffset); //(shortname from calendar.getGroups)+gmtoffset in minutes + Hashtable result = (Hashtable) xmlrpc.execute ("calendar.getWeek", params); + + + + ArrayList thisWeekEventsList=new ArrayList(); + + ArrayList day_keys=new ArrayList(); + + for (Enumeration e = result.keys() ; e.hasMoreElements() ; ){ + day_keys.add((String) e.nextElement()); + } + Collections.sort(day_keys); + + for(Iterator i = day_keys.iterator(); i.hasNext(); ){ + Hashtable day = (Hashtable) result.get((String) i.next()); + ArrayList order_keys = new ArrayList(); + + for (Enumeration ee = day.keys() ; ee.hasMoreElements() ; ){ + order_keys.add((String) ee.nextElement()); + } + Collections.sort(order_keys); + + for (Iterator ii = order_keys.iterator(); ii.hasNext();){ + Hashtable event = (Hashtable) day.get((String) ii.next()); + thisWeekEventsList.add(event); + } + } + + + ParameterExpander.setValueForKey( + aValueMap, + key, + thisWeekEventsList + ); + } + catch (Throwable t) { + Throwable s = ExceptionFunctions.traceCauseException(t); + aLogger.error("Error while accessing radicalendar: " + s.getClass().getName()+","+ s.getMessage()); + } + } +} diff --git a/source/mircoders/producer/UnIndexingProducerNode.java b/source/mircoders/producer/UnIndexingProducerNode.java index 8589f75f..371ece7a 100755 --- a/source/mircoders/producer/UnIndexingProducerNode.java +++ b/source/mircoders/producer/UnIndexingProducerNode.java @@ -30,6 +30,7 @@ package mircoders.producer; import java.util.Map; +import java.io.File; import mir.entity.Entity; import mir.entity.adapter.EntityAdapter; @@ -37,22 +38,25 @@ import mir.log.LoggerWrapper; import mir.producer.ProducerFailure; import mir.producer.ProducerNode; import mir.util.ParameterExpander; +import mir.util.FileFunctions; import mircoders.entity.EntityContent; import mircoders.search.IndexUtil; public class UnIndexingProducerNode implements ProducerNode { private String contentKey; private String indexPath; + private File indexBasePath; - public UnIndexingProducerNode(String aContentKey, String pathToIndex) { + public UnIndexingProducerNode(File anIndexBasePath, String aContentKey, String pathToIndex) { contentKey = aContentKey; indexPath=pathToIndex; + indexBasePath = anIndexBasePath; } public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure { Object data; Entity entity; - String index=null; + File indexFile; long startTime; long endTime; @@ -60,7 +64,8 @@ public class UnIndexingProducerNode implements ProducerNode { startTime = System.currentTimeMillis(); try { - index = ParameterExpander.expandExpression(aValueMap, indexPath); + indexFile = FileFunctions.getAbsoluteOrRelativeFile(indexBasePath, ParameterExpander.expandExpression(aValueMap, indexPath)); + data = ParameterExpander.findValueForKey( aValueMap, contentKey ); if (! (data instanceof EntityAdapter)) { @@ -71,9 +76,9 @@ public class UnIndexingProducerNode implements ProducerNode { if (! (entity instanceof EntityContent)) { throw new ProducerFailure("UnIndexingProducerNode: value of '"+contentKey+"' is not a content EntityAdapter, but a " + entity.getClass().getName() + " adapter", null); } - aLogger.info("UnIndexing " + (String) entity.getFieldValue("id") + " out of " + index); + aLogger.info("UnIndexing " + entity.getFieldValue("id") + " out of " + indexFile.getAbsolutePath()); - IndexUtil.unindexEntity((EntityContent) entity, index); + IndexUtil.unindexEntity((EntityContent) entity, indexFile); } catch (Throwable t) { aLogger.error("Error while unindexing content: " + t.getMessage()); diff --git a/source/mircoders/producer/reader/SupplementalProducerNodeBuilders.java b/source/mircoders/producer/reader/SupplementalProducerNodeBuilders.java index 11466302..783010eb 100755 --- a/source/mircoders/producer/reader/SupplementalProducerNodeBuilders.java +++ b/source/mircoders/producer/reader/SupplementalProducerNodeBuilders.java @@ -30,35 +30,38 @@ package mircoders.producer.reader; import java.util.Map; +import java.io.File; -import mir.entity.adapter.EntityAdapterModel; import mir.producer.ProducerNode; import mir.producer.reader.DefaultProducerNodeBuilders; import mir.producer.reader.ProducerConfigExc; import mir.producer.reader.ProducerNodeBuilderLibrary; -import mir.util.xml.XMLParserEngine; -import mir.util.xml.XMLReaderTool; +import mir.producer.reader.ProducerNodeBuilder; import mir.util.xml.XMLParserExc; +import mir.util.xml.XMLReaderTool; import mircoders.producer.ContentMarkingProducerNode; import mircoders.producer.ContentModifyingProducerNode; import mircoders.producer.IndexingProducerNode; import mircoders.producer.MediaGeneratingProducerNode; import mircoders.producer.PDFGeneratingProducerNode; import mircoders.producer.PDFPreFormattingProducerNode; +import mircoders.producer.RadicalendarProducerNode; import mircoders.producer.UnIndexingProducerNode; public class SupplementalProducerNodeBuilders { - public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary, EntityAdapterModel aModel) throws ProducerConfigExc { + public static void registerBuilders(ProducerNodeBuilderLibrary aBuilderLibrary, File aBasePath) throws ProducerConfigExc { aBuilderLibrary.registerBuilder("ModifyContent", ContentModifyingProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("MarkContent", ContentMarkingProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("GenerateMedia", MediaGeneratingProducerNodeBuilder.class); - aBuilderLibrary.registerBuilder("IndexContent",ContentIndexingProducerNodeBuilder.class); - aBuilderLibrary.registerBuilder("UnIndexContent",ContentUnIndexingProducerNodeBuilder.class); + aBuilderLibrary.registerFactory("IndexContent", new ContentIndexingProducerNodeBuilder.factory(aBasePath)); + aBuilderLibrary.registerFactory("UnIndexContent", new ContentUnIndexingProducerNodeBuilder.factory(aBasePath)); aBuilderLibrary.registerBuilder("PDFPreFormat", PDFPreFormattingProducerNodeBuilder.class); aBuilderLibrary.registerBuilder("PDFGenerate", PDFGeneratingProducerNodeBuilder.class); + aBuilderLibrary.registerBuilder("Radicalendar", RadicalendarProducerNodeBuilder.class); +// aBuilderLibrary.registerBuilder("ReportChangedFiles", ); } private final static String MARKER_KEY_ATTRIBUTE = DefaultProducerNodeBuilders.KEY_ATTRIBUTE; @@ -75,7 +78,7 @@ public class SupplementalProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(MARKER_KEY_ATTRIBUTE); }; @@ -91,23 +94,37 @@ public class SupplementalProducerNodeBuilders { private final static String[] INDEXER_SUBNODES = {}; public static class ContentIndexingProducerNodeBuilder extends DefaultProducerNodeBuilders.AbstractProducerNodeBuilder { - private String key; private String pathToIndex; + private File indexBasePath; + + private static class factory implements ProducerNodeBuilderFactory { + private File sourceBasePath; - public ContentIndexingProducerNodeBuilder() { + public factory(File aSourceBasePath) { + sourceBasePath = aSourceBasePath; + } + + public ProducerNodeBuilder makeBuilder() { + return new ContentIndexingProducerNodeBuilder(sourceBasePath); + } + } + + public ContentIndexingProducerNodeBuilder(File anIndexBasePath) { super(INDEXER_SUBNODES); + + indexBasePath = anIndexBasePath; } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, INDEXER_REQUIRED_ATTRIBUTES, INDEXER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, INDEXER_REQUIRED_ATTRIBUTES, INDEXER_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(INDEXER_KEY_ATTRIBUTE); pathToIndex = (String) anAttributes.get(INDEXER_INDEX_ATTRIBUTE); }; public ProducerNode constructNode() { - return new IndexingProducerNode(key,pathToIndex); + return new IndexingProducerNode(indexBasePath, key, pathToIndex); }; } @@ -118,23 +135,38 @@ public class SupplementalProducerNodeBuilders { private final static String[] UNINDEXER_SUBNODES = {}; public static class ContentUnIndexingProducerNodeBuilder extends DefaultProducerNodeBuilders.AbstractProducerNodeBuilder { - private String key; private String pathToIndex; - public ContentUnIndexingProducerNodeBuilder() { + private File indexBasePath; + + private static class factory implements ProducerNodeBuilderFactory { + private File indexBasePath; + + public factory(File aSourceBasePath) { + indexBasePath = aSourceBasePath; + } + + public ProducerNodeBuilder makeBuilder() { + return new ContentUnIndexingProducerNodeBuilder(indexBasePath); + } + } + + public ContentUnIndexingProducerNodeBuilder(File anIndexBasePath) { super(UNINDEXER_SUBNODES); + + indexBasePath = anIndexBasePath; } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, UNINDEXER_REQUIRED_ATTRIBUTES, UNINDEXER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, UNINDEXER_REQUIRED_ATTRIBUTES, UNINDEXER_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(UNINDEXER_KEY_ATTRIBUTE); pathToIndex = (String) anAttributes.get(UNINDEXER_INDEX_ATTRIBUTE); }; public ProducerNode constructNode() { - return new UnIndexingProducerNode(key,pathToIndex); + return new UnIndexingProducerNode(indexBasePath, key,pathToIndex); }; } @@ -156,7 +188,7 @@ public class SupplementalProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, CONTENT_MODIFIER_REQUIRED_ATTRIBUTES, CONTENT_MODIFIER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, CONTENT_MODIFIER_REQUIRED_ATTRIBUTES, CONTENT_MODIFIER_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(CONTENT_MODIFIER_KEY_ATTRIBUTE); field = (String) anAttributes.get(CONTENT_MODIFIER_FIELD_ATTRIBUTE); @@ -182,7 +214,7 @@ public class SupplementalProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, MEDIA_REQUIRED_ATTRIBUTES, MEDIA_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, MEDIA_REQUIRED_ATTRIBUTES, MEDIA_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(MEDIA_KEY_ATTRIBUTE); }; @@ -215,7 +247,7 @@ public class SupplementalProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); key = (String) anAttributes.get(MARKER_KEY_ATTRIBUTE); numLinesBetweenImages = (String) anAttributes.get(PDF_NUM_LINES_ATTRIBUTE); @@ -233,7 +265,6 @@ public class SupplementalProducerNodeBuilders { } public static class PDFGeneratingProducerNodeBuilder extends DefaultProducerNodeBuilders.AbstractProducerNodeBuilder { - private final static String MARKER_KEY_ATTRIBUTE = DefaultProducerNodeBuilders.KEY_ATTRIBUTE; private final static String PDF_GENERATOR_ATTRIBUTE = "generator"; private final static String PDF_DESTINATION_ATTRIBUTE = "destination"; private final static String PDF_STYLESHEET_ATTRIBUTE = "stylesheet"; @@ -251,7 +282,7 @@ public class SupplementalProducerNodeBuilders { } public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { - mir.util.xml.XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); + XMLReaderTool.checkAttributes(anAttributes, MARKER_REQUIRED_ATTRIBUTES, MARKER_OPTIONAL_ATTRIBUTES); generator = (String) anAttributes.get(PDF_GENERATOR_ATTRIBUTE); destination = (String) anAttributes.get(PDF_DESTINATION_ATTRIBUTE); @@ -262,6 +293,77 @@ public class SupplementalProducerNodeBuilders { return new PDFGeneratingProducerNode(generator,destination,stylesheet); }; } + + public static class RadicalendarProducerNodeBuilder extends DefaultProducerNodeBuilders.AbstractProducerNodeBuilder { + private final static String RC_KEY_ATTRIBUTE = "key"; + private final static String RC_GROUPNAME_ATTRIBUTE = "groupname"; + private final static String RC_GMTOFFSET_ATTRIBUTE = "gmtoffset"; + private final static String[] RC_REQUIRED_ATTRIBUTES = {RC_KEY_ATTRIBUTE,RC_GROUPNAME_ATTRIBUTE,RC_GMTOFFSET_ATTRIBUTE}; + private final static String[] RC_OPTIONAL_ATTRIBUTES = {}; + private final static String[] RC_SUBNODES = {}; + private String key; + private String groupname; + private String gmtoffset; + + public RadicalendarProducerNodeBuilder() { + super(RC_SUBNODES); + } + + public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { + XMLReaderTool.checkAttributes(anAttributes, RC_REQUIRED_ATTRIBUTES, RC_OPTIONAL_ATTRIBUTES); + + key = (String) anAttributes.get(RC_KEY_ATTRIBUTE); + groupname = (String) anAttributes.get(RC_GROUPNAME_ATTRIBUTE); + gmtoffset = (String) anAttributes.get(RC_GMTOFFSET_ATTRIBUTE); + } + + public ProducerNode constructNode() { + return new RadicalendarProducerNode(key,groupname,gmtoffset); + } + + } + + + /** + * Builder for {@link mircoders.producer.ChangedFilesReportingProducerNode} + * nodes. + */ +/* + private static class ChangeReportingProducerNodeBuilder extends DefaultProducerNodeBuilders.AbstractProducerNodeBuilder { + private final static String DESTINATION_FILE_ATTRIBUTE = "reportFile"; + private final static String LOCK_FILE_ATTRIBUTE = "lockfile"; + private final static String BASE_PATH_ATTRIBUTE = "basepath"; + private final static String EXCLUDED_PATHS_ATTRIBUTE = "excludedpaths"; + private final static String FLUSH_ATTRIBUTE = "flush"; + private final static String[] REQUIRED_ATTRIBUTES = {DESTINATION_FILE_ATTRIBUTE}; + private final static String[] OPTIONAL_ATTRIBUTES = {LOCK_FILE_ATTRIBUTE, BASE_PATH_ATTRIBUTE, EXCLUDED_PATHS_ATTRIBUTE, FLUSH_ATTRIBUTE}; + private final static String[] SUBNODES = {}; + + private String reportFile; + private String lockFile; + private String basePath; + private String excludedPaths; + private String flush; + + public ChangeReportingProducerNodeBuilder() { + super(SUBNODES); + } + + public void setAttributes(Map anAttributes) throws ProducerConfigExc, XMLParserExc { + XMLReaderTool.checkAttributes(anAttributes, REQUIRED_ATTRIBUTES, OPTIONAL_ATTRIBUTES); + + reportFile = XMLReaderTool.getStringAttributeWithDefault(anAttributes, DESTINATION_FILE_ATTRIBUTE, null); + lockFile = XMLReaderTool.getStringAttributeWithDefault(anAttributes, LOCK_FILE_ATTRIBUTE, null); + basePath = XMLReaderTool.getStringAttributeWithDefault(anAttributes, BASE_PATH_ATTRIBUTE, ""); + excludedPaths = XMLReaderTool.getStringAttributeWithDefault(anAttributes, EXCLUDED_PATHS_ATTRIBUTE, ""); + flush = XMLReaderTool.getStringAttributeWithDefault(anAttributes, FLUSH_ATTRIBUTE, "1"); + }; + + public ProducerNode constructNode() { + return new ChangedFilesReportingProducerNode(reportFile, lockFile, basePath, excludedPaths, flush); + }; + } +*/ } diff --git a/source/mircoders/search/AudioSearchTerm.java b/source/mircoders/search/AudioSearchTerm.java index ffbaec1a..34684196 100755 --- a/source/mircoders/search/AudioSearchTerm.java +++ b/source/mircoders/search/AudioSearchTerm.java @@ -30,15 +30,18 @@ package mircoders.search; -import java.util.Map; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; import javax.servlet.http.HttpServletRequest; import mir.entity.Entity; -import mir.entity.EntityList; +import mir.entity.EntityBrowser; import mir.storage.StorageObjectFailure; import mircoders.entity.EntityContent; import mircoders.storage.DatabaseContentToMedia; +import mircoders.storage.DatabaseAudio; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -49,8 +52,16 @@ public class AudioSearchTerm extends SearchTerm{ } public void index(Document doc, Entity entity) throws StorageObjectFailure{ - EntityList audio = DatabaseContentToMedia.getInstance().getAudio((EntityContent) entity); - if (audio != null && audio.size()>0){ + // EntityList audio = DatabaseContentToMedia.getInstance().getAudio((EntityContent) entity); + Vector extraTables = new Vector(); + extraTables.add("content_x_media cxm"); + Iterator audios = new EntityBrowser( + DatabaseAudio.getInstance(), "i", extraTables, + "cxm.content_id="+entity.getId()+"and cxm.media_id=i.id", + "i.id desc", 30, -1, 0); + + + if (audios != null && audios.hasNext()){ doc.add(Field.Keyword(matchField,"y")); } } diff --git a/source/mircoders/search/ImagesSearchTerm.java b/source/mircoders/search/ImagesSearchTerm.java index b1fa9aef..275cb44e 100755 --- a/source/mircoders/search/ImagesSearchTerm.java +++ b/source/mircoders/search/ImagesSearchTerm.java @@ -31,16 +31,20 @@ package mircoders.search; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; +import java.util.Vector; import javax.servlet.http.HttpServletRequest; import mir.entity.Entity; -import mir.entity.EntityList; +import mir.entity.EntityBrowser; import mir.storage.StorageObjectFailure; import mircoders.entity.EntityContent; -import mircoders.storage.DatabaseContentToMedia; +import mircoders.entity.EntityImages; +import mircoders.storage.DatabaseImages; + import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -51,15 +55,25 @@ public class ImagesSearchTerm extends SearchTerm{ } public void index(Document doc, Entity entity) throws StorageObjectFailure{ - EntityList images = DatabaseContentToMedia.getInstance().getImages((EntityContent) entity); - if (images != null && images.size()>0){ + Vector extraTables = new Vector(); + extraTables.add("content_x_media cxm"); + + Iterator images = new EntityBrowser( + DatabaseImages.getInstance(), "i", extraTables, + "cxm.content_id="+entity.getId()+"and cxm.media_id=i.id", + "i.id desc", 30, -1, 0); + + + if (images != null && images.hasNext()){ doc.add(Field.Keyword(matchField,"y")); String imageURLString = ""; - for(int k=0;k 0)) { + if ((videos != null) && (videos.hasNext())) { doc.add(Field.Keyword(matchField, "y")); } } diff --git a/source/mircoders/servlet/ServletHelper.java b/source/mircoders/servlet/ServletHelper.java index f9f4971c..1fa09018 100755 --- a/source/mircoders/servlet/ServletHelper.java +++ b/source/mircoders/servlet/ServletHelper.java @@ -30,6 +30,7 @@ package mircoders.servlet; import java.io.PrintWriter; +import java.io.IOException; import java.util.Locale; import java.util.Map; @@ -51,7 +52,7 @@ public class ServletHelper { private static LoggerWrapper logger = new LoggerWrapper("ServletModule.Helper"); public static Map makeGenerationData(HttpServletRequest aRequest, HttpServletResponse aResponse, Locale[] aLocales) throws ServletModuleExc { - return makeGenerationData(aRequest, aResponse, aLocales, "bundles.adminlocal", "bundles.admin"); + return makeGenerationData(aRequest, aResponse, aLocales, "etc/bundles/adminlocal", "bundles/admin"); } public static Map makeGenerationData(HttpServletRequest aRequest, HttpServletResponse aResponse, Locale[] aLocales, String aBundle) throws ServletModuleExc { @@ -61,7 +62,7 @@ public class ServletHelper { public static Map makeGenerationData(HttpServletRequest aRequest, HttpServletResponse aResponse, Locale[] aLocales, String aBundle, String aDefaultBundle) throws ServletModuleExc { try { MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); - Map result=GeneratorHelper.makeBasicGenerationData(aLocales,aBundle,aDefaultBundle); + Map result = GeneratorHelper.makeBasicGenerationData(aLocales, aBundle, aDefaultBundle); if (configuration.getString("Mir.Admin.ShowLoggedinUsers").equals("1")) { result.put("loggedinusers", MirGlobal.getLoggedInUsers()); } @@ -112,11 +113,26 @@ public class ServletHelper { } } + public static void generateInfoMessage(HttpServletRequest aRequest, HttpServletResponse aResponse, + Locale[] aLocales, String aBundle, String aDefaultBundle, String aMessage, String anArgument1, String anArgument2) throws ServletModuleExc { + Map responseData = makeGenerationData(aRequest, aResponse, aLocales, aBundle, aDefaultBundle); + responseData.put("message", aMessage); + responseData.put("argument1", anArgument1); + responseData.put("argument2", anArgument2); + + try { + generateResponse(aResponse.getWriter(), responseData, "infomessage.template"); + } + catch (IOException e) { + throw new ServletModuleFailure(e); + } + } + public static void redirect(HttpServletResponse aResponse, String aQuery) throws ServletModuleExc, ServletModuleFailure { try { aResponse.sendRedirect(aResponse.encodeRedirectURL(MirPropertiesConfiguration.instance().getString("RootUri") + "/servlet/Mir?"+aQuery)); } - catch (Throwable t) { + catch (IOException t) { throw new ServletModuleFailure("ServletModule.redirect: " +t.getMessage(), t); } } diff --git a/source/mircoders/servlet/ServletModuleAbuse.java b/source/mircoders/servlet/ServletModuleAbuse.java index 48825984..e026be60 100755 --- a/source/mircoders/servlet/ServletModuleAbuse.java +++ b/source/mircoders/servlet/ServletModuleAbuse.java @@ -84,7 +84,7 @@ public class ServletModuleAbuse extends ServletModule { String anId, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction, String anErrorMessage) throws ServletModuleExc { try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); responseData.put("id", anId); responseData.put("type", aType); @@ -203,7 +203,7 @@ public class ServletModuleAbuse extends ServletModule { URLBuilder urlBuilder = new URLBuilder(); try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); urlBuilder.setValue("module", "Abuse"); urlBuilder.setValue("do", "showfilters"); @@ -222,7 +222,7 @@ public class ServletModuleAbuse extends ServletModule { URLBuilder urlBuilder = new URLBuilder(); try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); urlBuilder.setValue("module", "Abuse"); urlBuilder.setValue("do", "showsettings"); @@ -280,7 +280,7 @@ public class ServletModuleAbuse extends ServletModule { URLBuilder urlBuilder = new URLBuilder(); try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); urlBuilder.setValue("module", "Abuse"); urlBuilder.setValue("do", "showlog"); responseData.put("thisurl", urlBuilder.getQuery()); diff --git a/source/mircoders/servlet/ServletModuleAdmin.java b/source/mircoders/servlet/ServletModuleAdmin.java index ccc81ece..568983bf 100755 --- a/source/mircoders/servlet/ServletModuleAdmin.java +++ b/source/mircoders/servlet/ServletModuleAdmin.java @@ -29,15 +29,16 @@ */ package mircoders.servlet; -import java.util.Locale; +import java.io.IOException; +import java.io.Writer; import java.util.Map; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; +import mir.servlet.ServletModuleExc; import mir.servlet.ServletModuleFailure; import mir.util.CachingRewindableIterator; import mir.util.URLBuilder; @@ -55,10 +56,9 @@ public class ServletModuleAdmin extends ServletModule public void superusermenu(HttpServletRequest aRequest, HttpServletResponse aResponse) { URLBuilder urlBuilder = new URLBuilder(); - int count; try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest)); urlBuilder.setValue("module", "Admin"); urlBuilder.setValue("do", "superusermenu"); @@ -71,13 +71,50 @@ public class ServletModuleAdmin extends ServletModule } } + /** + * Servlet handler method to reload the configuration for scripts. + * The output will be aimed at shell sripts. + */ + public void reload(HttpServletRequest aRequest, HttpServletResponse aResponse) { + String result = "reload successfull"; + + try { + MirGlobal.reloadConfigurations(); + } + catch (Throwable t) { + result = "error occurred while reloading: " +t.toString(); + } + + try { + Writer writer = aResponse.getWriter(); + writer.write(result); + } + catch (IOException e) { + throw new ServletModuleFailure(e); + } + } + + /** + * Servlet handler method to reload the configuration. + */ + public void reloadconfiguration(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { + try { + MirGlobal.reloadConfigurations(); + ServletHelper.generateInfoMessage(aRequest, aResponse, getLocales(aRequest), + "bundles/admin", "etc/bundles/adminlocal", "reloadSuccessfull", "", ""); + } + catch (Throwable t) { + ServletHelper.generateInfoMessage(aRequest, aResponse, getLocales(aRequest), + "bundles/admin", "etc/bundles/adminlocal", "reloadFailed", t.toString(), ""); + } + } + public void start(HttpServletRequest aRequest, HttpServletResponse aResponse) { String defaultStartTemplate = configuration.getString("Mir.StartTemplate"); - String sessionUrl = aResponse.encodeURL(""); try { - Map mergeData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale(aRequest)} - , "bundles.admin", "bundles.adminlocal"); + Map mergeData = ServletHelper.makeGenerationData(aRequest, aResponse, getLocales(aRequest), + "bundles/admin", "etc/bundles/adminlocal"); mergeData.put("messages", new CachingRewindableIterator( new EntityIteratorAdapter("", "webdb_create desc", 10, diff --git a/source/mircoders/servlet/ServletModuleArticleType.java b/source/mircoders/servlet/ServletModuleArticleType.java index 3073b8bf..1a99da2a 100755 --- a/source/mircoders/servlet/ServletModuleArticleType.java +++ b/source/mircoders/servlet/ServletModuleArticleType.java @@ -31,9 +31,7 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleArticleType; -import mircoders.storage.DatabaseArticleType; /** * @@ -53,9 +51,8 @@ public class ServletModuleArticleType extends ServletModule logger = new LoggerWrapper("ServletModule.ArticleType"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "articleType"; - mainModule = new ModuleArticleType(DatabaseArticleType.getInstance()); + mainModule = new ModuleArticleType(); } catch (Exception e) { logger.error("Initialization of ServletModuleArticleType failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleAudio.java b/source/mircoders/servlet/ServletModuleAudio.java index fe04cb15..e57cbe79 100755 --- a/source/mircoders/servlet/ServletModuleAudio.java +++ b/source/mircoders/servlet/ServletModuleAudio.java @@ -54,7 +54,6 @@ public class ServletModuleAudio extends ServletModuleUploadedMedia { moduleName = "Audio"; try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "audio"; mainModule = new ModuleUploadedMedia(DatabaseAudio.getInstance()); } diff --git a/source/mircoders/servlet/ServletModuleBreaking.java b/source/mircoders/servlet/ServletModuleBreaking.java index 3a7a06b3..dd4ea8d3 100755 --- a/source/mircoders/servlet/ServletModuleBreaking.java +++ b/source/mircoders/servlet/ServletModuleBreaking.java @@ -55,9 +55,8 @@ public class ServletModuleBreaking extends ServletModule logger = new LoggerWrapper("ServletModule.Breaking"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "breakingNews"; - mainModule = new ModuleBreaking(DatabaseBreaking.getInstance()); + mainModule = new ModuleBreaking(); } catch (Exception e) { logger.error("Initialisation of ServletModuleBreaking failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleComment.java b/source/mircoders/servlet/ServletModuleComment.java index de606b0f..40cdd78d 100755 --- a/source/mircoders/servlet/ServletModuleComment.java +++ b/source/mircoders/servlet/ServletModuleComment.java @@ -30,15 +30,6 @@ package mircoders.servlet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import mir.entity.adapter.EntityAdapterModel; import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; @@ -46,17 +37,15 @@ import mir.servlet.ServletModule; import mir.servlet.ServletModuleExc; import mir.servlet.ServletModuleFailure; import mir.servlet.ServletModuleUserExc; -import mir.util.CachingRewindableIterator; -import mir.util.HTTPRequestParser; -import mir.util.JDBCStringRoutines; -import mir.util.SQLQueryBuilder; -import mir.util.URLBuilder; +import mir.util.*; import mircoders.entity.EntityComment; import mircoders.global.MirGlobal; import mircoders.module.ModuleComment; -import mircoders.module.ModuleContent; import mircoders.storage.DatabaseComment; -import mircoders.storage.DatabaseContent; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.*; /* * ServletModuleComment - controls navigation for Comments @@ -67,16 +56,13 @@ import mircoders.storage.DatabaseContent; public class ServletModuleComment extends ServletModule { - private ModuleContent moduleContent; - private static ServletModuleComment instance = new ServletModuleComment(); public static ServletModule getInstance() { return instance; } private ServletModuleComment() { logger = new LoggerWrapper("ServletModule.Comment"); try { - mainModule = new ModuleComment(DatabaseComment.getInstance()); - moduleContent = new ModuleContent(DatabaseContent.getInstance()); + mainModule = new ModuleComment(); } catch (Exception e) { logger.error("servletmodule comment could not be initialized:" + e.getMessage()); @@ -122,7 +108,7 @@ public class ServletModuleComment extends ServletModule comment = model.makeEntityAdapter("comment", mainModule.getById(anId)); } else { - List fields = DatabaseComment.getInstance().getFields(); + List fields = DatabaseComment.getInstance().getFieldNames(); responseData.put("new", Boolean.TRUE); comment = new HashMap(); Iterator i = fields.iterator(); @@ -201,7 +187,6 @@ public class ServletModuleComment extends ServletModule HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); SQLQueryBuilder queryBuilder = new SQLQueryBuilder(); - String queryField = ""; String searchField = requestParser.getParameter("searchfield"); String searchText = requestParser.getParameter("searchtext"); String searchIsPublished = requestParser.getParameter("searchispublished"); @@ -259,12 +244,10 @@ public class ServletModuleComment extends ServletModule HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); URLBuilder urlBuilder = new URLBuilder(); - EntityAdapterModel model; int count; try { Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); - model = MirGlobal.localizer().dataModel().adapterModel(); Object commentList = new CachingRewindableIterator( @@ -333,8 +316,6 @@ public class ServletModuleComment extends ServletModule Map withValues = getIntersectingValues(aRequest, DatabaseComment.getInstance()); - String content_id = aRequest.getParameter("id"); - if (!withValues.containsKey("is_published")) withValues.put("is_published","0"); if (!withValues.containsKey("is_html")) @@ -349,7 +330,7 @@ public class ServletModuleComment extends ServletModule logAdminUsage(aRequest, id, "object modified"); if (returnUrl!=null){ - redirect(aResponse, returnUrl); + ServletHelper.redirect(aResponse, returnUrl); } else editObject(aRequest, aResponse, idParam); diff --git a/source/mircoders/servlet/ServletModuleCommentStatus.java b/source/mircoders/servlet/ServletModuleCommentStatus.java index 0ed1df2f..71767a0b 100755 --- a/source/mircoders/servlet/ServletModuleCommentStatus.java +++ b/source/mircoders/servlet/ServletModuleCommentStatus.java @@ -31,9 +31,7 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleCommentStatus; -import mircoders.storage.DatabaseCommentStatus; public class ServletModuleCommentStatus extends ServletModule @@ -45,9 +43,8 @@ public class ServletModuleCommentStatus extends ServletModule logger = new LoggerWrapper("ServletModule.CommentStatus"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "commentStatus"; - mainModule = new ModuleCommentStatus(DatabaseCommentStatus.getInstance()); + mainModule = new ModuleCommentStatus(); } catch (Throwable e) { logger.error("Initialization of ServletModuleCommentStatus failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleContent.java b/source/mircoders/servlet/ServletModuleContent.java index 912df40f..5feb152c 100755 --- a/source/mircoders/servlet/ServletModuleContent.java +++ b/source/mircoders/servlet/ServletModuleContent.java @@ -43,6 +43,7 @@ import javax.servlet.http.HttpServletResponse; import mir.entity.adapter.EntityAdapterModel; import mir.entity.adapter.EntityIteratorAdapter; +import mir.entity.adapter.EntityAdapter; import mir.log.LoggerWrapper; import mir.misc.StringUtil; import mir.servlet.ServletModule; @@ -54,19 +55,15 @@ import mir.util.JDBCStringRoutines; import mir.util.SQLQueryBuilder; import mir.util.StringRoutines; import mir.util.URLBuilder; +import mir.generator.Generator; import mircoders.entity.*; import mircoders.global.MirGlobal; import mircoders.module.ModuleContent; import mircoders.storage.DatabaseContent; import mircoders.storage.DatabaseContentToTopics; -/* - * ServletModuleContent - - * deliver html for the article admin form. - * - * @version $Id: ServletModuleContent.java,v 1.52.2.14 2004/01/18 17:31:00 zapata Exp $ - * @author rk, mir-coders - * +/** + * Article admin interface code */ public class ServletModuleContent extends ServletModule @@ -81,7 +78,7 @@ public class ServletModuleContent extends ServletModule logger = new LoggerWrapper("ServletModule.Content"); try { - contentModule = new ModuleContent(DatabaseContent.getInstance()); + contentModule = new ModuleContent(); mainModule = contentModule; } catch (Throwable e) { @@ -159,8 +156,7 @@ public class ServletModuleContent extends ServletModule editObject(aRequest, aResponse, null); } - public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { try { Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance()); @@ -181,8 +177,6 @@ public class ServletModuleContent extends ServletModule String id = mainModule.add(withValues); logAdminUsage(aRequest, id, "object added"); - List topics; - DatabaseContentToTopics.getInstance().setTopics(id, aRequest.getParameterValues("to_topic")); editObject(aRequest, aResponse, id); @@ -192,8 +186,7 @@ public class ServletModuleContent extends ServletModule } } - public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { String idParam = aRequest.getParameter("id"); if (idParam == null) throw new ServletModuleExc("Invalid call: id not supplied "); @@ -204,8 +197,7 @@ public class ServletModuleContent extends ServletModule * Attaches media to an article * */ - public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { String mediaIdParam = aRequest.getParameter("mid"); String articleId = aRequest.getParameter("articleid"); @@ -263,9 +255,7 @@ public class ServletModuleContent extends ServletModule { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); - String returnUrl = requestParser.getParameter("returnurl"); - - String idParam = aRequest.getParameter("id"); + String idParam = requestParser.getParameter("id"); if (idParam == null) throw new ServletModuleExc("Wrong call: (id) is missing"); @@ -286,9 +276,7 @@ public class ServletModuleContent extends ServletModule { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); - String returnUrl = requestParser.getParameter("returnurl"); - - String idParam = aRequest.getParameter("id"); + String idParam = requestParser.getParameter("id"); if (idParam == null) throw new ServletModuleExc("Wrong call: (id) is missing"); @@ -309,9 +297,7 @@ public class ServletModuleContent extends ServletModule { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); - String returnUrl = requestParser.getParameter("returnurl"); - - String idParam = aRequest.getParameter("id"); + String idParam = requestParser.getParameter("id"); if (idParam == null) throw new ServletModuleExc("Wrong call: (id) is missing"); @@ -333,9 +319,7 @@ public class ServletModuleContent extends ServletModule try { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); - String returnUrl = requestParser.getParameter("returnurl"); - - String idParam = aRequest.getParameter("id"); + String idParam = requestParser.getParameter("id"); if (idParam == null) throw new ServletModuleExc("Wrong call: (id) is missing"); @@ -344,8 +328,6 @@ public class ServletModuleContent extends ServletModule Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance()); - String content_id = aRequest.getParameter("id"); - withValues.put("is_produced", "0"); if (!withValues.containsKey("is_published")) withValues.put("is_published","0"); @@ -407,7 +389,7 @@ public class ServletModuleContent extends ServletModule responseData.put("mayUnlock", new Boolean(MirGlobal.accessControl().article().mayUnlockArticle(user, id))); } else { - List fields = DatabaseContent.getInstance().getFields(); + List fields = DatabaseContent.getInstance().getFieldNames(); responseData.put("new", Boolean.TRUE); article = new HashMap(); Iterator i = fields.iterator(); @@ -507,13 +489,10 @@ public class ServletModuleContent extends ServletModule HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); URLBuilder urlBuilder = new URLBuilder(); - EntityAdapterModel model; int count; try { Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); - model = MirGlobal.localizer().dataModel().adapterModel(); - Object articleList = new CachingRewindableIterator( new EntityIteratorAdapter( aWhereClause, anOrderByClause, nrEntitiesPerListPage, @@ -593,8 +572,7 @@ public class ServletModuleContent extends ServletModule } } - public void listchildren(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void listchildren(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { try { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); String articleId = requestParser.getParameter("article_id"); @@ -602,7 +580,7 @@ public class ServletModuleContent extends ServletModule if (articleId == null) throw new ServletModuleExc("ServletModuleContent.listchildren: article_id not set!"); - returnList(aRequest, aResponse, "to_content = " + articleId, "", 0, null); + returnList(aRequest, aResponse, "to_content = " + articleId, "webdb_create desc", 0, null); } catch (Throwable e) { throw new ServletModuleFailure(e); @@ -612,9 +590,9 @@ public class ServletModuleContent extends ServletModule public void setparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); - String articleId = aRequest.getParameter("childid"); - String parentId = aRequest.getParameter("id"); - String returnUrl = aRequest.getParameter("returnurl"); + String articleId = requestParser.getParameter("childid"); + String parentId = requestParser.getParameter("id"); + String returnUrl = requestParser.getParameter("returnurl"); if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId)) throw new ServletModuleExc("Article has been locked"); @@ -631,7 +609,7 @@ public class ServletModuleContent extends ServletModule throw new ServletModuleFailure(e); } - redirect(aResponse, returnUrl); + ServletHelper.redirect(aResponse, returnUrl); } public void clearparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc @@ -654,6 +632,24 @@ public class ServletModuleContent extends ServletModule throw new ServletModuleFailure("ServletModuleContent.clearparent: " + e.getMessage(), e); } - redirect(aResponse, returnUrl); + ServletHelper.redirect(aResponse, returnUrl); + } + + public void showPreview(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { + try { + HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); + String articleId = requestParser.getParameter("id"); + EntityAdapter article = model.makeEntityAdapter("content", mainModule.getById(articleId)); + String preview = requestParser.getParameterWithDefault("preview", "default"); + + Map generationValues = new HashMap(); + Generator generator = + MirGlobal.localizer().adminInterface().prepareArticlePreview(preview, article, generationValues); + + generator.generate(aResponse.getWriter(), generationValues, logger); + } + catch (Exception e) { + throw new ServletModuleFailure(e); + } } } diff --git a/source/mircoders/servlet/ServletModuleFileEdit.java b/source/mircoders/servlet/ServletModuleFileEdit.java index 30a4bfb0..83540400 100755 --- a/source/mircoders/servlet/ServletModuleFileEdit.java +++ b/source/mircoders/servlet/ServletModuleFileEdit.java @@ -36,14 +36,12 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; -import java.io.StringReader; import java.io.StringWriter; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Vector; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -62,7 +60,7 @@ import mir.util.URLBuilder; * in the config file. * * @author $Author: zapata $ - * @version $Revision: 1.13.2.6 $ $Date: 2003/12/21 17:50:32 $ + * @version $Revision: 1.13.2.7 $ $Date: 2004/11/21 22:07:14 $ * */ @@ -121,7 +119,7 @@ public class ServletModuleFileEdit extends ServletModule String setting = settings[i].trim(); if (setting.length() > 0) { - List parts = StringRoutines.splitString(setting, ":"); + List parts = StringRoutines.splitStringWithEscape(setting, ':', '\\'); if (parts.size() != 4) { logger.error("config error: " + settings[i] + ", 4 parts expected"); } @@ -195,30 +193,37 @@ public class ServletModuleFileEdit extends ServletModule } } + /** + * Called when an edited file is saved by the user + */ public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); String filename = requestParser.getParameter("filename"); String subDirectory = requestParser.getParameter("subdirectory"); - String text = requestParser.getParameter("text"); + String text = + StringRoutines.performRegularExpressionReplacement( + requestParser.getParameter("text"), + "\r\n", + System.getProperty("line.separator")); FileEditDirectory directory = getDirectory(aRequest); try { File f = new File(new File(directory.getRootDirectory(), subDirectory), filename); if (validateDirectory(directory, f)) { - StringReader in = new StringReader(text); FileWriter out = new FileWriter(f); - - int c; - while ( (c = in.read()) != -1) - out.write(c); - in.close(); - out.close(); + try { + out.write(text.toCharArray()); + } + finally { + out.close(); + } logAdminUsage(aRequest, f.getAbsolutePath(), "object modified"); - - +/* + MirGlobal.getChangeEngine().getTracker().addChange(f.getCanonicalPath()); +*/ editFile(directory, filename, subDirectory, aRequest, aResponse); } } diff --git a/source/mircoders/servlet/ServletModuleHidden.java b/source/mircoders/servlet/ServletModuleHidden.java index d5d32ae0..03606308 100755 --- a/source/mircoders/servlet/ServletModuleHidden.java +++ b/source/mircoders/servlet/ServletModuleHidden.java @@ -29,13 +29,6 @@ */ package mircoders.servlet; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import mir.entity.adapter.EntityIteratorAdapter; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; @@ -47,7 +40,12 @@ import mir.util.HTTPRequestParser; import mir.util.JDBCStringRoutines; import mircoders.global.MirGlobal; import mircoders.module.ModuleContent; -import mircoders.storage.DatabaseContent; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; /* * ServletModuleHidden - output of so called "censored" articles @@ -67,7 +65,7 @@ public class ServletModuleHidden extends ServletModule logger = new LoggerWrapper("ServletModule.Hidden"); try { - mainModule = new ModuleContent(DatabaseContent.getInstance()); + mainModule = new ModuleContent(); } catch (StorageObjectFailure e) { logger.error("initialization of servletmoduleHidden failed: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleImages.java b/source/mircoders/servlet/ServletModuleImages.java index bfc301ec..0075463b 100755 --- a/source/mircoders/servlet/ServletModuleImages.java +++ b/source/mircoders/servlet/ServletModuleImages.java @@ -31,14 +31,12 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleImages; -import mircoders.storage.DatabaseImages; /* * ServletModuleImages - * - * @version $Id: ServletModuleImages.java,v 1.26.2.3 2003/10/23 14:55:25 rk Exp $ + * @version $Id: ServletModuleImages.java,v 1.26.2.4 2004/11/21 22:07:14 zapata Exp $ * @author RK, the mir-coders group */ @@ -55,9 +53,8 @@ public class ServletModuleImages extends ServletModuleUploadedMedia moduleName = "Images"; try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "image"; - mainModule = new ModuleImages(DatabaseImages.getInstance()); + mainModule = new ModuleImages(); } catch (Throwable e) { logger.error("Initialization of ServletModuleImages failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleLanguage.java b/source/mircoders/servlet/ServletModuleLanguage.java index 235a1603..616f3b68 100755 --- a/source/mircoders/servlet/ServletModuleLanguage.java +++ b/source/mircoders/servlet/ServletModuleLanguage.java @@ -31,9 +31,7 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleLanguage; -import mircoders.storage.DatabaseLanguage; /* * ServletModuleLanguage - @@ -53,9 +51,8 @@ public class ServletModuleLanguage extends ServletModule logger = new LoggerWrapper("ServletModule.Language"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "language"; - mainModule = new ModuleLanguage(DatabaseLanguage.getInstance()); + mainModule = new ModuleLanguage(); } catch (Throwable e) { logger.error("Initialization of ServletModuleLanguage failed: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleLocalizer.java b/source/mircoders/servlet/ServletModuleLocalizer.java index d6cd2088..39370af9 100755 --- a/source/mircoders/servlet/ServletModuleLocalizer.java +++ b/source/mircoders/servlet/ServletModuleLocalizer.java @@ -29,15 +29,6 @@ */ package mircoders.servlet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import mir.entity.adapter.EntityAdapter; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; import mir.servlet.ServletModuleExc; @@ -45,11 +36,15 @@ import mir.util.StringRoutines; import mircoders.entity.EntityComment; import mircoders.entity.EntityContent; import mircoders.global.MirGlobal; -import mircoders.localizer.MirAdminInterfaceLocalizer; import mircoders.module.ModuleComment; import mircoders.module.ModuleContent; -import mircoders.storage.DatabaseComment; -import mircoders.storage.DatabaseContent; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; public class ServletModuleLocalizer extends ServletModule { private static ServletModuleLocalizer instance = new ServletModuleLocalizer(); @@ -63,8 +58,8 @@ public class ServletModuleLocalizer extends ServletModule { try { logger = new LoggerWrapper("ServletModule.Localizer"); - contentModule = new ModuleContent(DatabaseContent.getInstance()); - commentModule = new ModuleComment(DatabaseComment.getInstance()); + contentModule = new ModuleContent(); + commentModule = new ModuleComment(); administerOperations = new Vector(); @@ -81,8 +76,8 @@ public class ServletModuleLocalizer extends ServletModule { } else { Map entry = new HashMap(); - entry.put("name", (String) parts.get(0)); - entry.put("url", (String) parts.get(1)); + entry.put("name", parts.get(0)); + entry.put("url", parts.get(1)); administerOperations.add(entry); } } @@ -99,15 +94,12 @@ public class ServletModuleLocalizer extends ServletModule { * * See also * {@link mircoders.localizer.MirAdminInterfaceLocalizer#simpleArticleOperations()} - * {@link mircoders.localizer.MirAdminInterfaceLocalizer$MirSimpleEntityOperation()} * * @param aRequest The originating request * @param anId The id of the article * @param anOperation The identifier of the operation to perform */ public void performCommentOperation(HttpServletRequest aRequest, String anId, String anOperation) { - MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation; - EntityAdapter comment; EntityComment entity; try { @@ -134,7 +126,7 @@ public class ServletModuleLocalizer extends ServletModule { performCommentOperation(aRequest, commentIdString, operationString); - redirect(aResponse, returnUrlString); + ServletHelper.redirect(aResponse, returnUrlString); } public void commentoperationbatch(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { @@ -161,12 +153,10 @@ public class ServletModuleLocalizer extends ServletModule { } } - redirect(aResponse, returnUrlString); + ServletHelper.redirect(aResponse, returnUrlString); } public void performArticleOperation(HttpServletRequest aRequest, String anId, String anOperation) { - MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation; - EntityAdapter article; EntityContent entity; try { @@ -192,7 +182,7 @@ public class ServletModuleLocalizer extends ServletModule { String returnUrlString = aRequest.getParameter("returnurl"); performArticleOperation(aRequest, articleIdString, operationString); - redirect(aResponse, returnUrlString); + ServletHelper.redirect(aResponse, returnUrlString); } public void articleoperationbatch(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { @@ -219,7 +209,7 @@ public class ServletModuleLocalizer extends ServletModule { } } - redirect(aResponse, returnUrlString); + ServletHelper.redirect(aResponse, returnUrlString); } public List getAdministerOperations() throws ServletModuleExc { diff --git a/source/mircoders/servlet/ServletModuleMediaType.java b/source/mircoders/servlet/ServletModuleMediaType.java index ab5a9f7c..94007f76 100755 --- a/source/mircoders/servlet/ServletModuleMediaType.java +++ b/source/mircoders/servlet/ServletModuleMediaType.java @@ -31,7 +31,6 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleMediaType; import mircoders.storage.DatabaseMediaType; @@ -44,9 +43,8 @@ public class ServletModuleMediaType extends ServletModule logger = new LoggerWrapper("ServletModule.MediaType"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "mediaType"; - mainModule = new ModuleMediaType(DatabaseMediaType.getInstance()); + mainModule = new ModuleMediaType(); } catch (Exception e) { logger.error("Initialization of ServletModuleArticleType failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleMediafolder.java b/source/mircoders/servlet/ServletModuleMediafolder.java index d0195e67..4ca4ae69 100755 --- a/source/mircoders/servlet/ServletModuleMediafolder.java +++ b/source/mircoders/servlet/ServletModuleMediafolder.java @@ -29,23 +29,20 @@ */ package mircoders.servlet; -/** - * - */ - -import java.util.GregorianCalendar; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import mir.log.LoggerWrapper; import mir.misc.StringUtil; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleMediafolder; import mircoders.storage.DatabaseMediafolder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.GregorianCalendar; +import java.util.Map; + +/** + * + */ public class ServletModuleMediafolder extends ServletModule { public static ServletModule getInstance() { return instance; } @@ -56,9 +53,8 @@ public class ServletModuleMediafolder extends ServletModule logger = new LoggerWrapper("ServletModule.Mediafolder"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "mediaFolder"; - mainModule = new ModuleMediafolder(DatabaseMediafolder.getInstance()); + mainModule = new ModuleMediafolder(); } catch (Throwable t) { logger.error("Failed to initialize ServletModuleMediafolder: " + t.toString()); diff --git a/source/mircoders/servlet/ServletModuleMessage.java b/source/mircoders/servlet/ServletModuleMessage.java index 31c22464..4850e527 100755 --- a/source/mircoders/servlet/ServletModuleMessage.java +++ b/source/mircoders/servlet/ServletModuleMessage.java @@ -29,18 +29,16 @@ */ package mircoders.servlet; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import mir.log.LoggerWrapper; import mir.servlet.ServletModule; import mir.servlet.ServletModuleFailure; -import mircoders.global.MirGlobal; import mircoders.module.ModuleMessage; import mircoders.storage.DatabaseMessages; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; + /** * Title: ServletModuleMessage * Description: @@ -61,9 +59,8 @@ public class ServletModuleMessage extends ServletModule logger = new LoggerWrapper("ServletModule.Messages"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "internalMessage"; - mainModule = new ModuleMessage(DatabaseMessages.getInstance()); + mainModule = new ModuleMessage(); } catch (Throwable e) { logger.error("initialization of ServletModuleMessage failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleOpenIndy.java b/source/mircoders/servlet/ServletModuleOpenIndy.java index 63cebcf7..bdb0f2ef 100755 --- a/source/mircoders/servlet/ServletModuleOpenIndy.java +++ b/source/mircoders/servlet/ServletModuleOpenIndy.java @@ -30,29 +30,9 @@ package mircoders.servlet; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.Vector; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - import gnu.regexp.RE; import gnu.regexp.REMatch; +import mir.bundle.Bundle; import mir.entity.Entity; import mir.generator.Generator; import mir.log.LoggerWrapper; @@ -61,52 +41,39 @@ import mir.servlet.ServletModule; import mir.servlet.ServletModuleExc; import mir.servlet.ServletModuleFailure; import mir.servlet.ServletModuleUserExc; -import mir.session.HTTPAdapters; -import mir.session.Request; -import mir.session.Session; -import mir.session.SessionHandler; -import mir.session.SimpleResponse; -import mir.session.UploadedFile; +import mir.session.*; import mir.storage.StorageObjectFailure; -import mir.util.ExceptionFunctions; -import mir.util.HTTPParsedRequest; -import mir.util.HTTPRequestParser; -import mir.util.StringRoutines; +import mir.util.*; import mircoders.entity.EntityComment; import mircoders.entity.EntityContent; import mircoders.global.CacheKey; import mircoders.global.MirGlobal; import mircoders.media.MediaUploadProcessor; +import mircoders.media.UnsupportedMediaTypeExc; import mircoders.module.ModuleComment; import mircoders.module.ModuleContent; import mircoders.module.ModuleMediaType; +import mircoders.media.UnsupportedMediaTypeExc; import mircoders.pdf.PDFGenerator; -import mircoders.search.AudioSearchTerm; -import mircoders.search.ContentSearchTerm; -import mircoders.search.ImagesSearchTerm; -import mircoders.search.KeywordSearchTerm; -import mircoders.search.TextSearchTerm; -import mircoders.search.TopicMatrixSearchTerm; -import mircoders.search.TopicSearchTerm; -import mircoders.search.UnIndexedSearchTerm; -import mircoders.search.VideoSearchTerm; -import mircoders.storage.DatabaseComment; -import mircoders.storage.DatabaseContent; -import mircoders.storage.DatabaseContentToMedia; -import mircoders.storage.DatabaseContentToTopics; -import mircoders.storage.DatabaseLanguage; -import mircoders.storage.DatabaseTopics; +import mircoders.search.*; +import mircoders.storage.*; import org.apache.commons.fileupload.FileItem; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; +import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Searcher; -import org.apache.struts.util.MessageResources; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.*; +import java.util.*; /* * ServletModuleOpenIndy - @@ -115,7 +82,7 @@ import org.apache.struts.util.MessageResources; * open-postings to the newswire * * @author mir-coders group - * @version $Id: ServletModuleOpenIndy.java,v 1.89.2.11 2004/02/08 21:05:03 zapata Exp $ + * @version $Id: ServletModuleOpenIndy.java,v 1.89.2.12 2004/11/21 22:07:14 zapata Exp $ * */ @@ -129,9 +96,11 @@ public class ServletModuleOpenIndy extends ServletModule private ModuleContent contentModule; private ModuleComment commentModule; private String directOp ="yes"; - // Singelton / Kontruktor private static ServletModuleOpenIndy instance = new ServletModuleOpenIndy(); - public static ServletModule getInstance() { return instance; } + + public static ServletModule getInstance() { + return instance; + } private ServletModuleOpenIndy() { super(); @@ -151,9 +120,9 @@ public class ServletModuleOpenIndy extends ServletModule emailAnArticleTemplate = configuration.getString("ServletModule.OpenIndy.MailableArticleTemplate"); sentMailTemplate = configuration.getString("ServletModule.OpenIndy.SentMailTemplate"); directOp = configuration.getString("DirectOpenposting").toLowerCase(); - commentModule = new ModuleComment(DatabaseComment.getInstance()); + commentModule = new ModuleComment(); mainModule = commentModule; - contentModule = new ModuleContent(DatabaseContent.getInstance()); + contentModule = new ModuleContent(); defaultAction = "defaultAction"; } catch (StorageObjectFailure e) { @@ -420,7 +389,7 @@ public class ServletModuleOpenIndy extends ServletModule } Map withValues = new HashMap(); - i = DatabaseContent.getInstance().getFields().iterator(); + i = DatabaseContent.getInstance().getFieldNames().iterator(); while (i.hasNext()) { String field = (String) i.next(); String value = parsedRequest.getParameter(field); @@ -501,7 +470,7 @@ public class ServletModuleOpenIndy extends ServletModule e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); Throwable cause = ExceptionFunctions.traceCauseException(e); - if (cause instanceof ModuleMediaType.UnsupportedMimeTypeExc) { + if (cause instanceof UnsupportedMediaTypeExc) { throw new ServletModuleUserExc("media.unsupportedformat", new String[] {}); } throw new ServletModuleFailure(e); @@ -570,7 +539,7 @@ public class ServletModuleOpenIndy extends ServletModule SimpleResponse response = new SimpleResponse( ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getResponseLocale(aRequest.getSession(), aRequest), getFallbackLocale(aRequest)}, - "bundles.open")); + "etc/bundles/open")); response.setResponseValue("actionURL", aResponse.encodeURL(MirGlobal.config().getString("RootUri") + "/servlet/OpenMir")+"?"+SESSION_REQUEST_KEY+"="+aRequest.getSession().getId()); @@ -791,7 +760,7 @@ public class ServletModuleOpenIndy extends ServletModule session.setAttribute("positionInResults", new Integer(newPosition)); } else { - String indexPath = configuration.getString("IndexPath"); + File indexFile = FileFunctions.getAbsoluteOrRelativeFile(configuration.getHome(), configuration.getString("IndexPath")); String creatorFragment = creatorTerm.makeTerm(req); if (creatorFragment != null) { @@ -838,10 +807,10 @@ public class ServletModuleOpenIndy extends ServletModule try { Searcher searcher = null; try { - searcher = new IndexSearcher(indexPath); + searcher = new IndexSearcher(IndexReader.open(indexFile)); } catch (IOException e) { - logger.debug("Can't open indexPath: " + indexPath); + logger.debug("Can't open indexPath: " + indexFile.getAbsolutePath()); throw new ServletModuleExc("Problem with Search Index! : " + e.toString()); } @@ -1111,7 +1080,7 @@ public class ServletModuleOpenIndy extends ServletModule public void deliver(PrintWriter anOutputWriter, HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator) throws ServletModuleFailure { try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}, "bundles.open"); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}, "etc/bundles/open"); responseData.put("data", aData); responseData.put("extra", anExtra); @@ -1131,7 +1100,7 @@ public class ServletModuleOpenIndy extends ServletModule public void deliver(PrintWriter anOutputWriter, HttpServletRequest aRequest, HttpServletResponse aResponse, Map aData, Map anExtra, String aGenerator,String aLocaleString) throws ServletModuleFailure { try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { new Locale(aLocaleString,""), getFallbackLocale(aRequest)}, "bundles.open"); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { new Locale(aLocaleString,""), getFallbackLocale(aRequest)}, "etc/bundles/open"); responseData.put("data", aData); responseData.put("extra", anExtra); @@ -1170,8 +1139,10 @@ public class ServletModuleOpenIndy extends ServletModule logger.warn("user error: " + anException.getMessage()); Map data = new HashMap(); - MessageResources messages = MessageResources.getMessageResources("bundles.open"); - data.put("errorstring", messages.getMessage(getLocale(aRequest), anException.getMessage(), anException.getParameters())); + Bundle bundle = + MirGlobal.getBundleFactory().getBundle("etc/bundles/open", new + String[] { getLocale(aRequest).getLanguage() }); + data.put("errorstring", bundle.getValue(anException.getMessage(), Arrays.asList(anException.getParameters()))); data.put("date", StringUtil.date2readableDateTime(new GregorianCalendar())); deliver(out, aRequest, aResponse, data, null, configuration.getString("ServletModule.OpenIndy.UserErrorTemplate")); diff --git a/source/mircoders/servlet/ServletModuleOtherMedia.java b/source/mircoders/servlet/ServletModuleOtherMedia.java index 01d9075d..d447c098 100755 --- a/source/mircoders/servlet/ServletModuleOtherMedia.java +++ b/source/mircoders/servlet/ServletModuleOtherMedia.java @@ -32,7 +32,6 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleUploadedMedia; import mircoders.storage.DatabaseOther; @@ -59,7 +58,6 @@ public class ServletModuleOtherMedia extends ServletModuleUploadedMedia { moduleName = "OtherMedia"; try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "otherMedia"; mainModule = new ModuleUploadedMedia(DatabaseOther.getInstance()); } diff --git a/source/mircoders/servlet/ServletModuleProducer.java b/source/mircoders/servlet/ServletModuleProducer.java index bac92a1d..f6e3b67a 100755 --- a/source/mircoders/servlet/ServletModuleProducer.java +++ b/source/mircoders/servlet/ServletModuleProducer.java @@ -29,15 +29,15 @@ */ package mircoders.servlet; -import java.io.PrintWriter; import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Vector; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -47,11 +47,7 @@ import mir.producer.ProducerFactory; import mir.servlet.ServletModule; import mir.servlet.ServletModuleFailure; import mir.util.HTTPRequestParser; -import mir.util.ResourceBundleGeneratorFunction; import mircoders.global.MirGlobal; -import mircoders.global.ProducerEngine; - -import org.apache.struts.util.MessageResources; public class ServletModuleProducer extends ServletModule { @@ -61,18 +57,6 @@ public class ServletModuleProducer extends ServletModule Object comments; int totalNrComments; - void generateResponse(String aGeneratorIdentifier, PrintWriter aWriter, Map aResponseData, Locale aLocale) { - Generator generator; - try { - generator = MirGlobal.localizer().generators().makeAdminGeneratorLibrary().makeGenerator(aGeneratorIdentifier); - MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(aResponseData); - aResponseData.put( "lang", new ResourceBundleGeneratorFunction( aLocale, MessageResources.getMessageResources("bundles.admin"))); - generator.generate(aWriter, aResponseData, logger); - } - catch (Throwable t) { - throw new ServletModuleFailure(t); - } - } private ServletModuleProducer() { super(); @@ -80,39 +64,30 @@ public class ServletModuleProducer extends ServletModule defaultAction="showProducerQueueStatus"; } - public void showMessage(HttpServletRequest aRequest, HttpServletResponse aResponse, String aMessage, String anArgument1, String anArgument2) { - Map responseData; - try { - responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); - responseData.put("message", aMessage); - responseData.put("argument1", anArgument1); - responseData.put("argument2", anArgument2); - - ServletHelper.generateResponse(aResponse.getWriter(), responseData, "infomessage.template"); - } - catch (Throwable t) { - throw new ServletModuleFailure(t); - } - } - + /** + * + * @param aRequest + * @param aResponse + */ public void showProducerQueueStatus(HttpServletRequest aRequest, HttpServletResponse aResponse) { Map generationData; Generator generator; List producersData; try { + // TODO: use ServletHelper generator = MirGlobal.localizer().generators().makeAdminGeneratorLibrary().makeGenerator("producerqueue.template"); generationData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); generationData.put( "thisurl", "module=Producer&do=showProducerQueueStatus"); producersData = new Vector(); - Iterator i = MirGlobal.localizer().producers().factories().iterator(); + Iterator i = MirGlobal.getProducerEngine().getFactories().iterator(); while (i.hasNext()) { ProducerFactory factory = (ProducerFactory) i.next(); List producerVerbs = new Vector(); - Iterator j = factory.verbs(); + Iterator j = factory.verbs().iterator(); while (j.hasNext()) { Map verbData = new HashMap(); ProducerFactory.ProducerVerb verb = (ProducerFactory.ProducerVerb) j.next(); @@ -130,7 +105,7 @@ public class ServletModuleProducer extends ServletModule } generationData.put("producers", producersData); - generationData.put("queue", MirGlobal.producerEngine().getQueueStatus()); + generationData.put("queue", MirGlobal.getProducerEngine().getQueueStatus()); generator.generate(aResponse.getWriter(), generationData, logger); } catch (Throwable t) { @@ -151,7 +126,7 @@ public class ServletModuleProducer extends ServletModule String verbParam = aRequest.getParameter("verb"); try { - MirGlobal.producerEngine().addJob(producerParam, verbParam); + MirGlobal.getProducerEngine().addJob(producerParam, verbParam); out.println("job added"); } catch (Throwable t) { @@ -164,24 +139,34 @@ public class ServletModuleProducer extends ServletModule } } + /** + * Servlet action to propduce a preconfigured combination of producers + * (e.g. "generate all new") + */ public void producerecipe(HttpServletRequest aRequest, HttpServletResponse aResponse) { try { String recipe = aRequest.getParameter("recipe"); MirGlobal.localizer().producers().produceRecipe(recipe); - showMessage(aRequest, aResponse, "recipeAddedToQueue", recipe, ""); + + ServletHelper.generateInfoMessage(aRequest, aResponse, + new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}, + "bundles/admin", "etc/bundles/adminlocal", "recipeAddedToQueue", recipe, ""); } catch (Throwable t) { throw new ServletModuleFailure(t); } } + /** + * Servlet action to enqueue a producer job + */ public void enqueue(HttpServletRequest aRequest, HttpServletResponse aResponse) { try { if (aRequest.getParameter("producer")!=null) { String producerParam = aRequest.getParameter("producer"); String verbParam = aRequest.getParameter("verb"); - MirGlobal.producerEngine().addJob(producerParam, verbParam); + MirGlobal.getProducerEngine().addJob(producerParam, verbParam); ServletHelper.redirect(aResponse, "Producer", "showProducerQueueStatus"); } @@ -196,12 +181,12 @@ public class ServletModuleProducer extends ServletModule HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); if (requestParser.getParameter("cancelall") != null) { - MirGlobal.producerEngine().cancelAllJobs(); + MirGlobal.getProducerEngine().cancelAllJobs(); } else { - List jobs = new Vector(requestParser.getParameterList("jobid")); + List jobs = new ArrayList(requestParser.getParameterList("jobid")); - MirGlobal.producerEngine().cancelJobs(jobs); + MirGlobal.getProducerEngine().cancelJobs(jobs); } ServletHelper.redirect(aResponse, "Producer", "showProducerQueueStatus"); } diff --git a/source/mircoders/servlet/ServletModuleTopics.java b/source/mircoders/servlet/ServletModuleTopics.java index 441f33b1..e7700d0e 100755 --- a/source/mircoders/servlet/ServletModuleTopics.java +++ b/source/mircoders/servlet/ServletModuleTopics.java @@ -32,18 +32,10 @@ package mircoders.servlet; import mir.log.LoggerWrapper; import mir.servlet.ServletModule; -import mircoders.global.MirGlobal; import mircoders.module.ModuleTopics; -import mircoders.storage.DatabaseTopics; /** * - *

Title:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 */ public class ServletModuleTopics extends ServletModule @@ -56,9 +48,8 @@ public class ServletModuleTopics extends ServletModule logger = new LoggerWrapper("ServletModule.Topics"); try { - model = MirGlobal.localizer().dataModel().adapterModel(); definition = "topic"; - mainModule = new ModuleTopics(DatabaseTopics.getInstance()); + mainModule = new ModuleTopics(); } catch (Throwable e) { logger.error("Initialization of ServletModuleTopics failed!: " + e.getMessage()); diff --git a/source/mircoders/servlet/ServletModuleUploadedMedia.java b/source/mircoders/servlet/ServletModuleUploadedMedia.java index 976d76a6..58067ea6 100755 --- a/source/mircoders/servlet/ServletModuleUploadedMedia.java +++ b/source/mircoders/servlet/ServletModuleUploadedMedia.java @@ -36,7 +36,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Vector; +import java.util.ArrayList; import javax.servlet.ServletContext; import javax.servlet.ServletOutputStream; @@ -68,7 +68,9 @@ import mircoders.entity.EntityContent; import mircoders.entity.EntityUploadedMedia; import mircoders.global.MirGlobal; import mircoders.media.MediaUploadProcessor; +import mircoders.media.UnsupportedMediaTypeExc; import mircoders.module.ModuleMediaType; +import mircoders.media.UnsupportedMediaTypeExc; import mircoders.storage.DatabaseComment; import mircoders.storage.DatabaseContent; @@ -96,12 +98,6 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { definition = "uploadedMedia"; logger = new LoggerWrapper("ServletModule.UploadedMedia"); - try { - model = MirGlobal.localizer().dataModel().adapterModel(); - } - catch (Throwable t) { - throw new ServletModuleFailure(t); - } } public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) @@ -116,7 +112,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { mediaValues.put("to_publisher", ServletHelper.getUser(aRequest).getId()); - Iterator i = mainModule.getStorageObject().getFields().iterator(); + Iterator i = mainModule.getStorageObject().getFieldNames().iterator(); while (i.hasNext()) { String field = (String) i.next(); String value = parsedRequest.getParameter(field); @@ -124,7 +120,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { mediaValues.put(field, value); } - List mediaList = new Vector(); + List mediaList = new ArrayList(); i = parsedRequest.getFiles().iterator(); while (i.hasNext()) { @@ -151,7 +147,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { logAdminUsage(aRequest, id, "object attached to article " + articleid); } - ((ServletModuleContent) ServletModuleContent.getInstance()).editObject(aRequest, aResponse, articleid); + (ServletModuleContent.getInstance()).editObject(aRequest, aResponse, articleid); return; @@ -170,7 +166,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { logAdminUsage(aRequest, id, "object attached to comment " + commentid); } - ((ServletModuleComment) ServletModuleComment.getInstance()).editObject(aRequest, aResponse, commentid); + (ServletModuleComment.getInstance()).editObject(aRequest, aResponse, commentid); return; } @@ -182,7 +178,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { catch (Throwable t) { Throwable cause = ExceptionFunctions.traceCauseException(t); - if (cause instanceof ModuleMediaType.UnsupportedMimeTypeExc) { + if (cause instanceof UnsupportedMediaTypeExc) { throw new ServletModuleUserExc("media.error.unsupportedformat", new String[] {}); } throw new ServletModuleFailure("ServletModuleUploadedMedia.insert: " + t.toString(), t); @@ -198,7 +194,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { configuration.getString("TempDir")); Map mediaValues = new HashMap(); - Iterator i = mainModule.getStorageObject().getFields().iterator(); + Iterator i = mainModule.getStorageObject().getFieldNames().iterator(); while (i.hasNext()) { String field = (String) i.next(); String value = parsedRequest.getParameter(field); @@ -241,6 +237,8 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { responseData.put("thisurl", aThisUrl); responseData.put("nexturl", aNextUrl); responseData.put("prevurl", aPreviousUrl); + responseData.put("returnurl", requestParser.getParameter("returnurl")); + responseData.put("from", Integer.toString(aFrom)); responseData.put("count", Integer.toString(aCount)); @@ -290,6 +288,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { urlBuilder.setValue("searchtext", requestParser.getParameter("searchtext")); urlBuilder.setValue("searchispublished", requestParser.getParameter("searchispublished")); urlBuilder.setValue("searchmediafolder", requestParser.getParameter("searchmediafolder")); + urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl")); urlBuilder.setValue("where", aWhereClause); urlBuilder.setValue("order", anOrderByClause); @@ -320,7 +319,6 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { SQLQueryBuilder queryBuilder = new SQLQueryBuilder(); - String queryField = ""; String searchField = requestParser.getParameter("searchfield"); String searchText = requestParser.getParameter("searchtext"); String searchIsPublished = requestParser.getParameter("searchispublished"); @@ -368,7 +366,7 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { int nrMedia = requestParser.getIntegerWithDefault("nrmedia", 1); int maxNrMedia=configuration.getInt("ServletModule.OpenIndy.MaxMediaUploadItems", 20); - List fields = mainModule.getStorageObject().getFields(); + List fields = mainModule.getStorageObject().getFieldNames(); Map media = new HashMap(); Iterator i = fields.iterator(); while (i.hasNext()) { @@ -380,14 +378,14 @@ public abstract class ServletModuleUploadedMedia extends ServletModule { responseData.put("new", Boolean.TRUE); responseData.put("articleid", requestParser.getParameter("articleid")); responseData.put("commentid", requestParser.getParameter("commentid")); - responseData.put("returnurl", null); + responseData.put("returnurl", requestParser.getParameter("returnurl")); if (nrMedia<=0) nrMedia=1; if (nrMedia>maxNrMedia) nrMedia=maxNrMedia; - List mediaFields = new Vector(); + List mediaFields = new ArrayList(); for (int j=0; jimplements abstract DB connection to the comment_x_media SQL table * * @author RK, mir-coders group - * @version $Id: DatabaseCommentToMedia.java,v 1.3.2.6 2004/01/18 17:31:01 zapata Exp $ + * @version $Id: DatabaseCommentToMedia.java,v 1.3.2.7 2004/11/21 22:07:14 zapata Exp $ * */ @@ -164,7 +164,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); ResultSet rs = executeSql(stmt, sql); @@ -183,7 +183,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ sql = "insert into " + mainTable + " (comment_id,media_id) values (" + commentId + "," + mediaId[i] + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -211,7 +211,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ String sql = "insert into " + mainTable + " (comment_id,media_id) values (" + commentId + "," + mediaId + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -236,7 +236,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -255,7 +255,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ sql = "insert into " + mainTable + " (comment_id,media_id) values (" + commentId + "," + mediaId + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -280,7 +280,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -306,7 +306,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -334,7 +334,7 @@ public class DatabaseCommentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); diff --git a/source/mircoders/storage/DatabaseContent.java b/source/mircoders/storage/DatabaseContent.java index 8d5e8095..53c00f79 100755 --- a/source/mircoders/storage/DatabaseContent.java +++ b/source/mircoders/storage/DatabaseContent.java @@ -83,7 +83,7 @@ public class DatabaseContent extends Database implements StorageObject { String sql = "update content set is_produced='0' where " + where; logger.debug("set unproduced: "+where); try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); executeUpdate(stmt,sql); diff --git a/source/mircoders/storage/DatabaseContentToMedia.java b/source/mircoders/storage/DatabaseContentToMedia.java index c99bf762..14a4a532 100755 --- a/source/mircoders/storage/DatabaseContentToMedia.java +++ b/source/mircoders/storage/DatabaseContentToMedia.java @@ -48,7 +48,7 @@ import mircoders.entity.EntityUploadedMedia; * implements abstract DB connection to the content_x_media SQL table * * @author RK, mir-coders group - * @version $Id: DatabaseContentToMedia.java,v 1.19.2.5 2004/01/18 17:31:01 zapata Exp $ + * @version $Id: DatabaseContentToMedia.java,v 1.19.2.6 2004/11/21 22:07:14 zapata Exp $ * */ @@ -161,7 +161,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); ResultSet rs = executeSql(stmt, sql); @@ -180,7 +180,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ sql = "insert into " + mainTable + " (content_id,media_id) values (" + contentId + "," + mediaId[i] + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -208,7 +208,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ String sql = "insert into " + mainTable + " (content_id,media_id) values (" + contentId + "," + mediaId + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -233,7 +233,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -252,7 +252,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ sql = "insert into " + mainTable + " (content_id,media_id) values (" + contentId + "," + mediaId + ")"; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -277,7 +277,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -304,7 +304,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); @@ -332,7 +332,7 @@ public class DatabaseContentToMedia extends Database implements StorageObject{ Connection con = null; Statement stmt = null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); int rs = executeUpdate(stmt, sql); diff --git a/source/mircoders/storage/DatabaseContentToTopics.java b/source/mircoders/storage/DatabaseContentToTopics.java index 2ad9fb2b..2186c5ef 100755 --- a/source/mircoders/storage/DatabaseContentToTopics.java +++ b/source/mircoders/storage/DatabaseContentToTopics.java @@ -76,8 +76,6 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ /** * This class return an EntityList of Topics - * @param EntityContent content - * @returns EntityList */ public EntityList getTopics(EntityContent content) { EntityList returnList=null; @@ -99,8 +97,7 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ } /** - * Returns a ArrayList of Integer-Objects from a content-id. - * @returns ArrayList + * Returns a List of String-Objects from a content-id. */ public List getTopicsOfContent(String contentId) throws StorageObjectFailure { @@ -110,13 +107,14 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ String sql = "select topic_id from " + mainTable + " where content_id=" + contentId; Connection con=null;Statement stmt=null; try { - con = getPooledCon(); + con = obtainConnection(); + // should be a preparedStatement because is faster stmt = con.createStatement(); ResultSet rs = executeSql(stmt,sql); if(rs!=null){ while(rs.next()){ - returnList.add(new Integer(rs.getInt("topic_id"))); + returnList.add(Integer.toString(rs.getInt("topic_id"))); } } } @@ -163,9 +161,9 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ List currentTopics = getTopicsOfContent(anArticleId); logger.debug("New topics = " + newTopics.toString()); logger.debug("Current topics = " + currentTopics.toString()); - List topicsToDelete = new Vector(currentTopics); + List topicsToDelete = new ArrayList(currentTopics); topicsToDelete.removeAll(newTopics); - List topicsToAdd = new Vector(newTopics); + List topicsToAdd = new ArrayList(newTopics); topicsToAdd.removeAll(currentTopics); logger.debug("to delete = " + topicsToDelete.toString()); logger.debug("to add = " + topicsToAdd.toString()); @@ -180,9 +178,9 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ Connection connection=null; Statement statement=null; try { - connection = getPooledCon(); + connection = obtainConnection(); statement = connection.createStatement(); - int rs = executeUpdate(statement, sql); + executeUpdate(statement, sql); } catch (Exception e) { logger.error("-- deleting topics failed"); @@ -205,10 +203,10 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ Connection connection=null; Statement statement=null; try { - connection = getPooledCon(); + connection = obtainConnection(); // should be a preparedStatement because is faster statement = connection.createStatement(); - int rs = executeUpdate(statement, sql); + executeUpdate(statement, sql); } catch (Exception e) { logger.error("-- adding topics failed"); @@ -234,10 +232,10 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ Connection con=null;Statement stmt=null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); - ResultSet rs = executeSql(stmt,sql); + executeSql(stmt,sql); } catch (Exception e) { //theLog.printDebugInfo("-- delete topics failed "); } finally { @@ -256,10 +254,10 @@ public class DatabaseContentToTopics extends Database implements StorageObject{ Connection con=null;Statement stmt=null; try { - con = getPooledCon(); + con = obtainConnection(); // should be a preparedStatement because is faster stmt = con.createStatement(); - ResultSet rs = executeSql(stmt,sql); + executeSql(stmt,sql); } catch (Exception e) { logger.error("-- delete topics failed "); diff --git a/templates/admin/FUNCTIONS.template b/templates/admin/FUNCTIONS.template index ff59dcb0..6c08aa3c 100755 --- a/templates/admin/FUNCTIONS.template +++ b/templates/admin/FUNCTIONS.template @@ -65,7 +65,7 @@
@@ -464,19 +467,20 @@ @@ -489,19 +493,20 @@ @@ -514,19 +519,20 @@ diff --git a/templates/admin/FUNCTIONS_media.template b/templates/admin/FUNCTIONS_media.template index 70ec3e1d..de87ba36 100755 --- a/templates/admin/FUNCTIONS_media.template +++ b/templates/admin/FUNCTIONS_media.template @@ -68,8 +68,12 @@ + + + + + - @@ -144,7 +148,12 @@

${s.title}
- ${s.creator}, ${s.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

+ ${sorig.creator} (${lang("general.translatedby", s.creator)}), ${sorig.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${sorig.to_media_other[0]["big_icon"]}"> - + ${s.to_media_images[0][ + src="${sorig.to_media_images[0]["icon_path"]}" + width="${sorig.to_media_images[0]["icon_width"]}" + height="${sorig.to_media_images[0]["icon_height"]}" + border=0 alt="${sorig.to_media_images[0]["title"]}"> ${s.description_parsed}
@@ -119,30 +126,37 @@ - + + + + + + + +

${i.title}
- ${i.creator}, ${i.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

+ ${aorig.creator} (${lang("general.translatedby", i.creator)}), ${aorig.creationdate.formatted["dd-MM-yyyy - HH:mm"]}

- + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_audio[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_video[0]["big_icon"]}"> - + + src="${config["Producer.DocRoot"]}/img/${aorig.to_media_other[0]["big_icon"]}"> - + ${i.to_media_images[0][ + src="${aorig.to_media_images[0]["icon_path"]}" + width="${aorig.to_media_images[0]["icon_width"]}" + height="${aorig.to_media_images[0]["icon_height"]}" + border=0 alt="${aorig.to_media_images[0]["title"]}"> ${i.description_parsed}
diff --git a/etc/scripts/bundletool.sh b/etc/scripts/bundletool.sh new file mode 100755 index 00000000..88b0d511 --- /dev/null +++ b/etc/scripts/bundletool.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +HOME=`dirname $0` + +for j in $HOME/../../bin/mir/WEB-INF/lib/*.jar; do + if [ "$CLASSPATH" ] ; then + CLASSPATH="$CLASSPATH:$j" + else + CLASSPATH="$j" + fi +done +export CLASSPATH + +if [ "$JAVA_HOME" ] ; then + if [ -z "$JAVACMD" ]; then + JAVACMD="$JAVA_HOME/bin/java" + fi +fi + +$JAVACMD tool.BundleTool $* diff --git a/etc/scripts/produce.sh b/etc/scripts/produce.sh new file mode 100755 index 00000000..535c2899 --- /dev/null +++ b/etc/scripts/produce.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo -e "http://your.mir.home/yourmirwebapp/servlet/Mir?login=youruser&password=yourpassword&module=Producer&do=produce&producer=$1&verb=$2\n-accept_all_cookies\n-dump" | lynx - diff --git a/etc/scripts/reload.sh b/etc/scripts/reload.sh new file mode 100755 index 00000000..2737590f --- /dev/null +++ b/etc/scripts/reload.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo -e "http://your.mir.home/yourmirwebapp/servlet/Mir?login=youruser&password=yourpassword&module=Admin&do=reload\n-accept_all_cookies \n-dump" | lynx - diff --git a/etc/server.xml b/etc/server.xml deleted file mode 100755 index 61eabc25..00000000 --- a/etc/server.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/lib/README.txt b/lib/README.txt index a49f9bf8..355c89fd 100755 --- a/lib/README.txt +++ b/lib/README.txt @@ -155,36 +155,26 @@ url : http://www.tfh-berlin.de/~knabe/java/multex description: nested exceptions todo : rename to multex-3.jar - -poolman ------------------------------------------------- -version : ?? -url : https://sourceforge.net/projects/poolman -url : http://www.codestudio.com/ -description: PoolMan is no longer available or supported - Connection and object pooling mechanisms: - they can now be found in application servers [...] - Tomcat and the Jakarta Project, and other - J2EE products and servers. -todo : find replacement - - postgresql ------------------------------------------------ -version : 7.2 (jdbc2-version) +version : 7.4 (jdbc2-version) url : http://jdbc.postgresql.org description: JDBC driver for postgresql database - -strutsmesg ------------------------------------------------- -version : ?? -url : -description: Extracted from struts 1.0 -todo : update - velocity ------------------------------------------------ version : 1.3.1 url : http://jakarta.apache.org/velocity description: template engine + +commons-pool-1.1 +------------------------------------------------ +version : 1.1 +url : http://jakarta.apache.org/commons-pool +description: generic object pooling framework + +commons-dbcp-1.1 +----------------------------------------------- +version : 1.1 +url : http://jakarta.apache.org/commons-dbcp +description: database connection pooling library diff --git a/lib/commons-dbcp-1.1.jar b/lib/commons-dbcp-1.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..c3c4d1f2ab35f9ca0c8222baf01ba2128d71fd1b GIT binary patch literal 100776 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

ubQ7MOJ7T{zvbte&h%4vMe(0*C8!U1CnSGTu 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

9Wv!tHKvb>dW>v9KG$aGjJL7*%89A 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 diff --git a/lib/commons-fileupload-1.0.jar b/lib/commons-fileupload-1.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..1ca4a9cd31aab5cdbcf1fbeaadf805cb41d09995 GIT binary patch literal 22379 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 QC{uq?RKEJlf7hA+0w~Z#ng9R* literal 0 HcmV?d00001 diff --git a/lib/commons-httpclient-2.0.jar b/lib/commons-httpclient-2.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..f58ec95a49f0674bf0b82bad372d4c56a1c8d7ca GIT binary patch literal 222618 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�wnrBdO2x|;>G7&LYe)^$f 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%0Akn$WY5JT8(-+e8^^CT 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

&NK28mfn#vom02snv_OHMaI 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 LAASK8skr|GDx7w& literal 0 HcmV?d00001 diff --git a/lib/commons-pool-1.1.jar b/lib/commons-pool-1.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..c61bde6c9bad543bcb67590dd9ac836a810f5458 GIT binary patch literal 39523 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%0DFiIis=^SN&^Kw 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�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 H4e0*>q;iEc literal 0 HcmV?d00001 diff --git a/lib/strutsmesg.jar b/lib/strutsmesg.jar deleted file mode 100755 index 5aeec6001255febe430c054e3e7c738cbe0621e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18667 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 VGpxWG0=RP;2y205O@s@G2LN+diUt4x diff --git a/lib/xmlrpc-1.2-b1.jar b/lib/xmlrpc-1.2-b1.jar new file mode 100755 index 0000000000000000000000000000000000000000..cc67714fff070218fbb45f00dde4a7b7cbf32969 GIT binary patch literal 108476 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 literal 0 HcmV?d00001 diff --git a/etc/web.xml b/meta/web.xml similarity index 64% rename from etc/web.xml rename to meta/web.xml index 42b57983..595c3046 100755 --- a/etc/web.xml +++ b/meta/web.xml @@ -126,43 +126,4 @@ application/pdf - - - - Protected Area - - /jsp/security/protected/* - - DELETE - GET - POST - PUT - - - - tomcat - role1 - - - - - - - - - FORM - Example Form-Based Authentication Area - - /jsp/security/login/login.jsp - /jsp/security/login/error.jsp - - - diff --git a/perms.sh-dist b/perms.sh-dist index 83cbdaf4..ae9f3129 100755 --- a/perms.sh-dist +++ b/perms.sh-dist @@ -1,7 +1,7 @@ #!/bin/sh # Where the installed system resides -INSTDIR=bin/mir +INSTDIR=`dirname $0`/bin/mir # The group all files belong to GROUP=www-data diff --git a/scripts/produce.sh b/scripts/produce.sh deleted file mode 100755 index 50d2c47f..00000000 --- a/scripts/produce.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo -e "http://admin.subtv.org/subtv/servlet/Mir?login=mir&password=mitmirnicht22&module=Producer&do=produce&producer=$1&verb=$2\n-accept_all_cookies\n-dump" | lynx - diff --git a/scripts/search.pl b/scripts/search.pl deleted file mode 100755 index 02f1ad15..00000000 --- a/scripts/search.pl +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/perl - -use CGI qw(:standard); -use LWP::UserAgent; -use URI::Escape; - -#this program takes, as CGI params, a query string "words" -#a syntax string "bool" (and|or), values of Y or N for the -#variables of the form hasVideo, hasAudio, hasImage, etc. -#and a variable topic corresponding to the desired topic title -#it then munges these variables into an appropriate request to htdig, -# does this request and forwards the results to the user - -$searchhost='http://prod.indymedia.nl/cgi-bin/htsearch'; - -$bool=param('bool'); -$hasVideo=param('hasVideo'); -$hasAudio=param('hasAudio'); -$hasImages=param('hasImages'); -$topic=param('topic'); -@topic_words=split(/\s+/,$topic); -@words=(); - -$querywords=''; -@words=split (/\s+/,param('words')) if param('words'); -push @words,@topic_words; -if (@words){ - -if ($bool eq "and"){ -$querywords=join " AND ", @words; -} -else{ -$querywords=join " OR ", @words; -} - -$querywords =~ s/\(\)/ /g; -$querywords="($querywords)"; -} - -if ($hasVideo eq "Y" || $hasAudio eq "Y" || $hasImages eq "Y"){ - $first=1; - if (@words){ - $querywords.=" AND "; -} - $querywords .= "("; - -if ($hasVideo eq "Y"){ - if (!$first){ - $querywords.=" OR"; - } - $querywords.=" RealVideo OR Video"; - $first=0; -} - -if ($hasAudio eq "Y"){ - if (!$first){ - $querywords.=" OR"; - } - $querywords.=" RealAudio OR Audio"; - $first=0; -} - -if ($hasImages eq "Y"){ - if (!$first){ - $querywords.=" OR"; - } - $querywords.=" ImagesGif OR ImagesJpeg"; - $first=0; -} - $querywords.=" )"; -} - -$querywords=uri_escape($querywords,"^A-Za-z0-9"); - -$query="words=$querywords&format=builtin-long&sort=score&method=boolean"; - -# propagate the config parameter if it is set - rob -$config=param('config'); -$query.="&config=$config" if $config; - - - -$ua = new LWP::UserAgent; -$ua->agent("AgentName/0.1 " . $ua->agent); - -# Create a request -my $req = new HTTP::Request POST => $searchhost; -$req->content_type('application/x-www-form-urlencoded'); -$req->content($query); - -# Pass request to the user agent and get a response back -my $res = $ua->request($req); - -# Check the outcome of the response -if ($res->is_success) { - print header; - print $res->content; -} else { - print header; - print "Search engine temporarily unavailable\n"; -} diff --git a/source/Mir.java b/source/Mir.java index d3673423..91be32de 100755 --- a/source/Mir.java +++ b/source/Mir.java @@ -28,50 +28,30 @@ * If you do not wish to do so, delete this exception statement from your version. */ -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Vector; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.UnavailableException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpSessionBindingEvent; -import javax.servlet.http.HttpSessionBindingListener; - +import mir.bundle.Bundle; import mir.config.MirPropertiesConfiguration; -import mir.servlet.AbstractServlet; -import mir.servlet.ServletModule; -import mir.servlet.ServletModuleDispatch; -import mir.servlet.ServletModuleExc; -import mir.servlet.ServletModuleUserExc; +import mir.servlet.*; import mir.util.ExceptionFunctions; import mir.util.StringRoutines; +import mir.log.LoggerWrapper; import mircoders.entity.EntityUsers; import mircoders.global.MirGlobal; import mircoders.module.ModuleUsers; import mircoders.servlet.ServletHelper; -import mircoders.storage.DatabaseUsers; - -import org.apache.struts.util.MessageResources; - +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.UnavailableException; +import javax.servlet.http.*; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.util.*; +import multex.Failure; /** * Mir.java - main servlet, that dispatches to servletmodules - * - * @author $Author: zapata $ - * @version $Id: Mir.java,v 1.49.2.11 2004/01/18 17:30:56 zapata Exp $ - * */ public class Mir extends AbstractServlet { private static ModuleUsers usersModule = null; @@ -80,29 +60,29 @@ public class Mir extends AbstractServlet { private static List loginLanguages = null; - protected List getLoginLanguages() throws ServletException { + private List getLoginLanguages() throws Failure { synchronized (Mir.class) { try { if (loginLanguages == null) { - MessageResources messageResources = - MessageResources.getMessageResources("bundles.adminlocal"); - MessageResources messageResources2 = - MessageResources.getMessageResources("bundles.admin"); - List languages = StringRoutines.splitString(MirGlobal.config().getString("Mir.Login.Languages", "en"), ";"); - loginLanguages = new Vector(); + loginLanguages = new ArrayList(); Iterator i = languages.iterator(); while (i.hasNext()) { String code = (String) i.next(); - Locale locale = new Locale(code, ""); - String name = messageResources.getMessage(locale, "languagename"); + + Bundle bundle = + MirGlobal.getBundleFactory().getBundle("etc/bundles/adminlocal", new String[] { code }); + Bundle defaultBundle = + MirGlobal.getBundleFactory().getBundle("bundles/admin", new String[] { code }); + + String name = bundle.getValue("languagename", Collections.EMPTY_LIST); if (name == null) { - name = messageResources2.getMessage(locale, "languagename"); + name = defaultBundle.getValue("languagename", Collections.EMPTY_LIST); } if (name == null) { @@ -119,7 +99,7 @@ public class Mir extends AbstractServlet { return loginLanguages; } catch (Throwable t) { - throw new ServletException(t.getMessage()); + throw new Failure("Error while retrieving the available login languages", t); } } } @@ -127,7 +107,7 @@ public class Mir extends AbstractServlet { public void init(ServletConfig config) throws ServletException { super.init(config); - usersModule = new ModuleUsers(DatabaseUsers.getInstance()); + usersModule = new ModuleUsers(); } protected String getDefaultLanguage(HttpServletRequest aRequest) { @@ -253,7 +233,7 @@ public class Mir extends AbstractServlet { } } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE)); throw new ServletException(t.toString()); } @@ -308,8 +288,21 @@ public class Mir extends AbstractServlet { Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] {getLocale(aRequest), getFallbackLocale()}); - MessageResources messages = MessageResources.getMessageResources("bundles.admin"); - responseData.put("errorstring", messages.getMessage(getLocale(aRequest), anException.getMessage(), anException.getParameters())); + Bundle bundle = + MirGlobal.getBundleFactory().getBundle("etc/bundles/adminlocal", new + String[] { getLocale(aRequest).getLanguage() }); + Bundle defaultBundle = + MirGlobal.getBundleFactory().getBundle("bundles/admin", new + String[] { getLocale(aRequest).getLanguage() }); + String message = + bundle.getValue(anException.getMessage(), Arrays.asList(anException.getParameters())); + + if (message==null) { + message = + defaultBundle.getValue(anException.getMessage(), Arrays.asList(anException.getParameters())); + } + + responseData.put("errorstring", message); responseData.put("date", new GregorianCalendar().getTime()); ServletHelper.generateResponse(aResponse.getWriter(), responseData, MirPropertiesConfiguration.instance().getString("Mir.UserErrorTemplate")); @@ -332,6 +325,22 @@ public class Mir extends AbstractServlet { } catch (Throwable e) { logger.error("Error handling error: " + e.toString()); + + try { + Throwable rootException = ExceptionFunctions.traceCauseException(anException); + + PrintWriter writer = aResponse.getWriter(); + writer.println("FATAL Error"); + writer.println("

" + rootException.toString()+"

"); + writer.println(""); + rootException.printStackTrace(writer); + writer.println(""); + writer.println(""); + writer.close(); + } + catch (Throwable t) { + + } } } diff --git a/source/OpenMir.java b/source/OpenMir.java index 1daa016a..dfdbe4dc 100755 --- a/source/OpenMir.java +++ b/source/OpenMir.java @@ -46,7 +46,7 @@ import mircoders.servlet.ServletModuleOpenIndy; * OpenMir.java - main servlet for open posting and comment feature to articles * * @author RK 1999-2001, the mir-coders group - * @version $Id: OpenMir.java,v 1.35.2.2 2003/10/23 14:55:26 rk Exp $ + * @version $Id: OpenMir.java,v 1.35.2.3 2004/11/21 22:07:13 zapata Exp $ * */ @@ -54,15 +54,14 @@ import mircoders.servlet.ServletModuleOpenIndy; public class OpenMir extends AbstractServlet { public void process(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletException, IOException { - if ((configuration.getString("RootUri") == null) || - configuration.getString("RootUri").equals("")) { - configuration.setProperty("RootUri", aRequest.getContextPath()); - } + if ((configuration.getString("RootUri") == null) || + configuration.getString("RootUri").equals("")) { + configuration.setProperty("RootUri", aRequest.getContextPath()); + } long startTime = System.currentTimeMillis(); long sessionConnectTime=0; - HttpSession session = aRequest.getSession(); checkLanguage(session, aRequest); diff --git a/source/default.properties b/source/default.properties index 15136d99..970cf9ac 100755 --- a/source/default.properties +++ b/source/default.properties @@ -1,35 +1,4 @@ # -# Sample config for Mir -# by Matthias 2001-09-12 -# -# The Mir software realizes a semi-dynamic web service: -# The web server that is accessed by users has pure static -# pages. These pages are generated by the Mir software that -# consists of a collection of Java servlets and HTML templates. -# Mir uses a database server to store the data that is needed to -# build the static site. -# So there are basically three parts in this config file: -# -# a) general setup -# b) static site config -# c) dynamic admin site -# d) database config -# -# edit this to suit your needs (here with sampleuser idfx) -# After you edited this file, build.sh has to be invoked. -# To be sure, also restart Tomcat. -# -# Note that for Mir to work, Tomcat has to be set up to handle all -# URLs that begin with /servlet. All other URLs are handled by Apache. -# -# The setup uses the following assumptions: -# The URL to reach the site is http://indy.code-fu.de -# The StorageRoot of this URL is /pub/Dokumente/Indymedia/de-tech/Mir -# All data is located below this directory, including the servlets. - - -# -# # GENERAL SETUP # @@ -43,7 +12,7 @@ Mir.Tech-email.name=mir-coders mailinglist Mir.Public-email.address=mir-coders@lists.indymedia.org Mir.Public-email.name=mir-coders mailinglist -Mir.Version=1.1beta +Mir.Version=1.1.0rc0 DirectOpenposting=yes # The name of the abuse config file (relative to the WEB-INF dir) @@ -61,7 +30,7 @@ Abuse.CookieMaxAge=168 #where to put the lucene index -IndexPath=/tmp/index +IndexPath=index TempDir=/tmp @@ -91,27 +60,33 @@ Mir.Admin.ShowLoggedinUsers=1 # Log admin activity? Mir.Admin.LogAdminActivity=0 +# Limit the length of text shown in lists (-1 means no limit) +Mir.Admin.ListTextLengthLimit=-1 + # Which usernames have admin priviliges (, seperated usernames) AccessControl.SuperUsers = admin # Locking enabled? AccessControl.LockingEnabled = 0 -# If locking enabled, should users lock articles before they +# If locking enabled, should users lock articles before they # can edit? AccessControl.LockingOptional = 1 # the templates Mir.Localizer.Producer.GeneratorLibrary= default=freemarker(etc/producer/) -Mir.Localizer.Admin.GeneratorLibrary= default=freemarker(templates/admin/) +Mir.Localizer.Admin.GeneratorLibrary= default=freemarker(templates/admin/),preview=freemarker(etc/producer) Mir.Localizer.OpenPosting.GeneratorLibrary= default=freemarker(etc/open/) # How should the custom operations (hide etc) in article and comment lists # be presented? # 0 = links, 1 = checkboxes, 2 = a listbox -Mir.Localizer.Admin.ListOperationsFlavor=1 - - +Mir.Localizer.Admin.ListOperationsFlavor=2 + +# Article previews, a comma seperated list of name = generator +Mir.Localizer.Admin.ArticlePreview = \ + default = preview::article.template +Mir.Localizer.Admin.ArticlePreviewLanguage=en # How should the topics be presented on the article edit page? # @@ -149,7 +124,7 @@ Mir.Localizer.OpenPosting.ContentProducers= media.new;articles.changed;startpage Mir.Localizer.OpenPosting.CommentProducers= articles.changed;synchronization.run # Which producers need to be called after the "produce all new" link is clicked from admin -Mir.Localizer.Producer.ProducerRecipes= +Mir.Localizer.Producer.ProducerRecipes= \ allnew = media.new;articles.changed;startpage.run;synchronization.run @@ -184,7 +159,7 @@ Producer.StorageRoot=/pub/Dokumente/Indymedia/de-tech/Mir/produced # FileEdit module # a list of directories to edit -# format: +# format: # :::<0|1 (recursion off or on)> [, ....] ServletModule.FileEdit.Configuration= \ @@ -274,11 +249,11 @@ Producer.Icon.BigText=text_big.gif Producer.HTML2FOStyleSheet=/some/dir/mir/etc/producer/html2fo.xsl # the following lines are used to construct PDFs on the fly from one or more articles -# for the moment, if you want to change anything else about your pdfs, you +# for the moment, if you want to change anything else about your pdfs, you # will have to learn some java! # -# keep in mind that there may not be enough room for all the text you enter as the -# value of one these options, if text doesn't appear, the only easy thing to do is +# keep in mind that there may not be enough room for all the text you enter as the +# value of one these options, if text doesn't appear, the only easy thing to do is # use less text! # # also, be sure to adjust the corresponding line height if you change a font size... @@ -304,12 +279,12 @@ PDF.Title.FontSize=24 PDF.Title.LineHeight=28 PDF.Title.FontFamily=courier -# footer is about two lines of small text which will appear at the bottom of every page +# footer is about two lines of small text which will appear at the bottom of every page PDF.Footer.String=Indymedia does blah. Content is good, and free to use for non-commercial purposes under the Open Content license. if you have questions, email someone. PDF.Footer.Height=54 PDF.Footer.FontSize=12 -PDF.Footer.FontFamily=helvetica +PDF.Footer.FontFamily=helvetica # how to format the index, i.e. the newsletter table of contents @@ -321,7 +296,7 @@ PDF.Index.FontFamily=helvetica PDF.Meta.Height=36 PDF.Meta.FontSize=14 -PDF.Meta.FontFamily=helvetica +PDF.Meta.FontFamily=helvetica RDF.Meta.DateFormat=yyyy-MM-dd HH:mm # how to format the article description @@ -403,8 +378,23 @@ Mir.DefaultTimezone= UTC # Default date/time format Mir.DefaultDateTimeFormat = yyyy-MM-dd HH:mm +# Compatibility feature: updated posting forms can +# support persistent uploads (that is, uploads remainig +# valid after validation errors). To support existing +# forms, by default it is off. +Localizer.OpenSession.PersistentUploadedFiles = 0 +# Should support for ftp-like uploads (uploads done +# outside of mir, but included into postings) be +# supported at all? +Localizer.OpenSession.AllowFTPUploads = 0 +# When uploading ftp files, should a list of available +# files be displayed? +Localizer.OpenSession.AllowFTPUploadSelection = 0 + +# What is the place where files are uploaded? +Localizer.OpenSession.FTPDirectory = /somewhere Localizer.OpenSession.article.EditTemplate = editarticle.template Localizer.OpenSession.article.DupeTemplate = dupearticle.template @@ -524,6 +514,18 @@ ServletModule.MediaType.DeleteConfirmationTemplate=confirm.template ServletModule.MediaType.EditTemplate=mediatype.template ServletModule.MediaType.ListTemplate=mediatypelist.template +# +# Object store configuration +# + +StoreContainer.EntityDefaultSize= 45 +StoreContainer.EntityListDefaultSize= 15 +StorableObjectEntity.Entity.DefaultSize= 300 +StorableObjectEntity.EntityList.DefaultSize= 100 +EntityTopics.Entity.DefaultSize= 200 +EntityTopics.EntityList.DefaultSize= 20 + + @@ -543,3 +545,6 @@ Producer.ExtLinkName=extlink.gif Producer.IntLinkName=intlink.gif Producer.MailLinkName=maillink.gif +# should the BasicBundleFactory is responsible for managing + * loaded bundles. It caches previously retrieved bundles to improve + * performance. + */ +public class BasicBundleFactory implements BundleFactory { + private Map directories; + private BundleLoader loader; + + public BasicBundleFactory(BundleLoader aLoader) { + directories = new HashMap(); + loader = aLoader; + } + + private Map getBundleDirectory(String aDirectory) { + synchronized (directories) { + Map result = (Map) directories.get(aDirectory); + + if (result == null) { + result = new HashMap(); + directories.put(aDirectory, result); + } + + return result; + } + } + + private Bundle loadBundle(String aDirectory, String[] aParameters) { + return loader.loadBundle(aDirectory, aParameters); + } + + public Bundle getBundle(String aDirectory, String[] aParameters) { + Map directory = getBundleDirectory(aDirectory); + List parameters = java.util.Arrays.asList(aParameters); + + Bundle result = (Bundle) directory.get(parameters); + + if (result==null) { + result = loadBundle(aDirectory, aParameters); + directory.put(parameters, result); + } + + return result; + } + + public void reload() { + synchronized (directories) { + directories.clear(); + } + } +} diff --git a/source/mir/bundle/Bundle.java b/source/mir/bundle/Bundle.java new file mode 100755 index 00000000..cec44e49 --- /dev/null +++ b/source/mir/bundle/Bundle.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.bundle; + +import java.util.List; + +public interface Bundle { + public String getValue(String aKey, List anArguments); +} diff --git a/source/mir/bundle/BundleFactory.java b/source/mir/bundle/BundleFactory.java new file mode 100755 index 00000000..7df1476b --- /dev/null +++ b/source/mir/bundle/BundleFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.bundle; + +public interface BundleFactory { + /** + * Retrieves a bundle + */ + public Bundle getBundle(String aDirectory, String[] aParameters); + + /** + * Invalidates the bundle cache + */ + public void reload(); +} diff --git a/source/mir/bundle/BundleLoader.java b/source/mir/bundle/BundleLoader.java new file mode 100755 index 00000000..7674e94c --- /dev/null +++ b/source/mir/bundle/BundleLoader.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.bundle; + +/** + *

+ * The BundleLoader is responsible for the physical loading of (abstract) + * {@link Bundle}s. A Bundle is identified by a directory + * and a set of parameters. The directory typically denotes the base of + * a set of Bundles, the parameters stand for a particular + * instance. E.g. the directory might stand for the purpose of the bundles, + * the parameters for the locale. + *

+ *

+ * BundleLoaders should not do any caching, since that's the + * responsibility of the {@link BasicBundleFactory}. + *

+ */ +public interface BundleLoader { + /** + * Loads the bundle specified by aDirectory and + * aParameters. + */ + public Bundle loadBundle(String aDirectory, String[] aParameters); +} diff --git a/source/mir/bundle/CascadingBundleFactory.java b/source/mir/bundle/CascadingBundleFactory.java new file mode 100755 index 00000000..b3a9920e --- /dev/null +++ b/source/mir/bundle/CascadingBundleFactory.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.bundle; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CascadingBundleFactory implements BundleFactory { + private BundleFactory masterFactory; + + /** {@inheritDoc} */ + public CascadingBundleFactory(BundleFactory aMasterFactory) { + masterFactory = aMasterFactory; + } + + /** {@inheritDoc} */ + public Bundle getBundle(final String aDirectory, final String[] aParameters) { + return + new Bundle() { + public String getValue(String aKey, List anArguments) { + String result = masterFactory.getBundle(aDirectory, aParameters).getValue(aKey, anArguments); + + if (aParameters.length>0 && result==null) { + List parameters = new ArrayList(Arrays.asList(aParameters)); + + while (result==null && parameters.size()>0) { + parameters.remove(parameters.size()-1); + result = masterFactory.getBundle( + aDirectory, (String[]) parameters.toArray(new String[0])).getValue(aKey, anArguments); + } + } + + return result; + } + }; + } + + /** {@inheritDoc} */ + public void reload() { + masterFactory.reload(); + } +} diff --git a/source/mir/bundle/PropertiesBundle.java b/source/mir/bundle/PropertiesBundle.java new file mode 100755 index 00000000..a7952852 --- /dev/null +++ b/source/mir/bundle/PropertiesBundle.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.bundle; + +import java.util.Properties; +import java.util.List; +import java.util.Iterator; + +import mir.util.StringParseRoutines; + +/** + * Bundle implementation using a {@link Properties} + * object. + */ + +public class PropertiesBundle implements Bundle { + private Properties properties; + + public PropertiesBundle(Properties aProperties) { + properties = aProperties; + } + + private String formatValue(String anExpression, List anArguments) { + StringBuffer result = new StringBuffer(); + + List parts = StringParseRoutines.parseBracketedExpression( + anExpression, '\\', "{", "}" ); + + Iterator i = parts.iterator(); + while (i.hasNext()) { + result.append(i.next()); + if (i.hasNext()) { + String expression = (String) i.next(); + try { + int parameterNr = Integer.parseInt(expression); + if (parameterNr>=0 && parameterNrWEB-INF dir of the + * deployed mir servlets. */ - public String getStringWithHome(String key) { - String returnString = getString(key); - - if (returnString == null) { - returnString = new String(); - } - - return getString("Home") + returnString; + public File getHome() { + return home; } /** - * Checks if one property is missing and adds a default value + * Returns a file based on a configuration setting. + * + * The file may be configured with an absolute path, or + * it may be a relative path. + * + * Relative paths work relative to {@link #home} : + * normally this is the WEB-INF dir in a + * deployed java servlet. */ - private void checkMissing() { - for (int i = 0; i < neededWithValue.length; i++) { - if (super.getProperty(neededWithValue[i].getKey()) == null) { - addProperty(neededWithValue[i].getKey(), neededWithValue[i].getValue()); - } - } - } + public File getFile(String aKey) { + String path = getString(aKey); - public File getFile(String key) throws FileNotFoundException { - String path = getStringWithHome(key); - File returnFile = new File(path); - - if (returnFile.exists()) { - return returnFile; - } else { - throw new FileNotFoundException(); + File result = new File(path); + if (result.isAbsolute()) { + return result; + } + else { + return new File(home, path); } } /** * @return the vlaue of this property as String * @param key the key of this property - * @see org.apache.commons.configuration.Configuration#getString(java.lang.String) */ public String getString(String key) { return getString(key, ""); @@ -204,11 +183,26 @@ public class MirPropertiesConfiguration extends ExtendedProperties { return object.toString(); } + public boolean getBoolean(String aKey, boolean aDefaultValue) { + try { + return getBoolean(aKey); + } + catch (Throwable t) { + return aDefaultValue; + } + } + + public boolean getBoolean(String aKey) { + String value = getString(aKey).trim(); + + return "1".equals(value) || "y".equalsIgnoreCase(value) || + "yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value); + } + /** * Returns a property according to the given key * @param key the key of the property * @return the value of the property as Object, if no property available it returns a empty String - * @see org.apache.commons.configuration.Configuration#getString(java.lang.String) */ public Object getProperty(String key) { if (super.getProperty(key) == null) { @@ -224,7 +218,6 @@ public class MirPropertiesConfiguration extends ExtendedProperties { public static class PropertiesConfigExc extends Exc { /** * Constructor for PropertiesConfigExc. - * @param arg0 */ public PropertiesConfigExc(String msg) { super(msg); @@ -237,32 +230,9 @@ public class MirPropertiesConfiguration extends ExtendedProperties { public static class PropertiesConfigFailure extends Failure { /** * Constructor for PropertiesConfigExc. - * @param arg0 */ public PropertiesConfigFailure(String msg, Throwable cause) { super(msg, cause); } } - - /** - * A Class for properties to be checked - * @author idefix - */ - private static class NeededProperty { - private String _key; - private String _value; - - public NeededProperty(String key, String value) { - _key = key; - _value = value; - } - - public String getKey() { - return _key; - } - - public String getValue() { - return _value; - } - } } diff --git a/source/mir/entity/AbstractEntity.java b/source/mir/entity/AbstractEntity.java index dcd493bd..a4e6585f 100755 --- a/source/mir/entity/AbstractEntity.java +++ b/source/mir/entity/AbstractEntity.java @@ -45,25 +45,16 @@ import mir.storage.StorageObjectFailure; * Base class the entities are derived from. Provides base functionality of * an entity. * - * @version $Id: AbstractEntity.java,v 1.8.2.2 2004/02/08 21:05:00 zapata Exp $ + * @version $Id: AbstractEntity.java,v 1.8.2.3 2004/11/21 22:07:13 zapata Exp $ */ public class AbstractEntity implements Entity { - protected static MirPropertiesConfiguration configuration; + protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); protected Map values; protected StorageObject storageObject; protected LoggerWrapper logger; - static { - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new RuntimeException(e.getMessage()); - } - } - public AbstractEntity() { logger = new LoggerWrapper("Entity"); @@ -74,7 +65,6 @@ public class AbstractEntity implements Entity { * Constructor * @param StorageObject The StorageObject of the Entity. */ - public AbstractEntity(StorageObject StorageObject) { this(); @@ -159,7 +149,7 @@ public class AbstractEntity implements Entity { * Returns the field names of the Entity */ public List getFieldNames() throws StorageObjectFailure { - return storageObject.getFields(); + return storageObject.getFieldNames(); } /** Returns whether fieldName is a valid field name of this Entity. diff --git a/source/mir/entity/EntityList.java b/source/mir/entity/EntityList.java index fad20bfa..a2e6cce6 100755 --- a/source/mir/entity/EntityList.java +++ b/source/mir/entity/EntityList.java @@ -27,7 +27,7 @@ * exception to your version of the file, but you are not obligated to do so. * If you do not wish to do so, delete this exception statement from your version. */ -package mir.entity; +package mir.entity; import java.util.ArrayList; import java.util.Set; @@ -52,38 +52,35 @@ import mir.storage.store.StoreUtil; * @version 1.1 (cleaned up) */ public class EntityList implements StorableObject { - protected static MirPropertiesConfiguration configuration; + protected static MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); protected LoggerWrapper logger; private ArrayList theEntityArrayList = new ArrayList(); private String whereClause, orderClause; - private StorageObject theStorage; + private StorageObject storage; private int count, offset, limit; - private int offsetnext = -1, offsetprev = -1; + private int nextOffset = -1; + private int previousOffset = -1; - static { - try { - configuration = MirPropertiesConfiguration.instance(); - } - catch (PropertiesConfigExc e) { - throw new RuntimeException("Unable to get configuration: " + e.getMessage()); - } - } - - /** - * Constructor. - */ public EntityList(){ logger = new LoggerWrapper("Entity.List"); } /* get/set EntityClass of Objects stored in EntityList */ - public void setStorage(StorageObject storage) { this.theStorage=storage; } - public StorageObject getStorage() { return theStorage; } + public void setStorage(StorageObject aStorage) { + storage=aStorage; + } - public void setLimit(int limit) { this.limit = limit; } + public StorageObject getStorage() { + return storage; + } + + public void setLimit(int aLimit) { + limit = aLimit; + } /** * Sets the WHERE clause that fetched the Entities of this EntityList from the database. + * * @param wc The string that contains the WHERE clause */ public void setWhere(String wc) { @@ -92,6 +89,7 @@ public class EntityList implements StorableObject { /** * Returns the WHERE clause that returned this EntityList from the database + * * @return whereClause The WHERE clause */ public String getWhere() { @@ -100,6 +98,7 @@ public class EntityList implements StorableObject { /** * Sets the sorting criterium of this EntityList + * * @param oc */ public void setOrder(String oc) { @@ -108,6 +107,7 @@ public class EntityList implements StorableObject { /** * Returns the sorting criterium. + * * @return orderClause The sort order */ public String getOrder() { @@ -116,14 +116,16 @@ public class EntityList implements StorableObject { /** * Sets the number of rows that match the WHERE clause + * * @param i The number of rows that match the WHERE clause */ public void setCount(int i) { - this.count = i; + count = i; } /** * Returns the number of rows that match the WHERE clause + * * @return The number of rows ... */ public int getCount() { @@ -132,6 +134,7 @@ public class EntityList implements StorableObject { /** * Sets the offset + * * @param i The offset */ public void setOffset(int i) { @@ -140,6 +143,7 @@ public class EntityList implements StorableObject { /** * Returns the offset + * * @return offset */ public int getOffset() { @@ -148,54 +152,61 @@ public class EntityList implements StorableObject { /** * Sets the offset of the next batch of Entities. + * * @param i The next offset */ public void setNextBatch(int i) { - offsetnext = i; + nextOffset = i; } /** * Returns the offset of the next batch of Entities. + * * @return offset of the next batch */ public int getNextBatch() { - return offsetnext; + return nextOffset; } /** * Returns whether there is a next batch within the WHERE clause + * * @return true if yes, false if no. */ public boolean hasNextBatch() { - return (offsetnext >= 0); + return (nextOffset >= 0); } /** * Sets the offset of the previous batch. + * * @param i the previous offset */ public void setPrevBatch(int i) { - offsetprev = i; + previousOffset = i; } /** * Returns the offset of the previous batch. + * * @return offset of the previous batch */ public int getPrevBatch() { - return offsetprev; + return previousOffset; } /** * Returns whether there is a previous batch. + * * @return true if yes, false if no */ public boolean hasPrevBatch() { - return (offsetprev >= 0); + return (previousOffset >= 0); } /** * Returns the start index of the batch. + * * @return */ public int getFrom() { @@ -204,17 +215,19 @@ public class EntityList implements StorableObject { /** * Returns the end index of the batch. + * * @return */ public int getTo() { if (hasNextBatch()) - return offsetnext; + return nextOffset; else return count; } /** * Inserts an Entity into the EntityList. + * * @param anEntity The entity to be inserted. */ @@ -253,14 +266,18 @@ public class EntityList implements StorableObject { public Set getNotifyOnReleaseSet() { return null; } public StoreIdentifier getStoreIdentifier() { - if ( theStorage!=null ) { + if ( storage!=null ) { return - new StoreIdentifier( this, StoreContainerType.STOC_TYPE_ENTITYLIST, - StoreUtil.getEntityListUniqueIdentifierFor( theStorage.getTableName(), - whereClause, orderClause, offset, limit )); + new StoreIdentifier( + this, StoreContainerType.STOC_TYPE_ENTITYLIST, + StoreUtil.getEntityListUniqueIdentifierFor( storage.getTableName(), + whereClause, orderClause, offset, limit )); + } + else { + logger.warn("EntityList could not return StoreIdentifier"); + + return null; } - logger.warn("EntityList could not return StoreIdentifier"); - return null; } } diff --git a/source/mir/entity/adapter/EntityListAdapter.java b/source/mir/entity/adapter/EntityListAdapter.java index 7df00efa..19f37be7 100755 --- a/source/mir/entity/adapter/EntityListAdapter.java +++ b/source/mir/entity/adapter/EntityListAdapter.java @@ -30,8 +30,8 @@ package mir.entity.adapter; import java.util.AbstractList; +import java.util.ArrayList; import java.util.List; -import java.util.Vector; import mir.entity.Entity; import mir.entity.EntityBrowser; @@ -53,7 +53,7 @@ public class EntityListAdapter extends AbstractList { browser = aBrowser; skip = aSkip; maximumLength = aMaximumLength; - cache = new Vector(); + cache = new ArrayList(); } protected EntityListAdapter(EntityAdapterModel aModel, String aDefinition, EntityBrowser aBrowser, int aMaximumLength) { diff --git a/source/mir/generator/CompositeGeneratorLibrary.java b/source/mir/generator/CompositeGeneratorLibrary.java index d1c5651b..324363fc 100755 --- a/source/mir/generator/CompositeGeneratorLibrary.java +++ b/source/mir/generator/CompositeGeneratorLibrary.java @@ -32,16 +32,16 @@ package mir.generator; import java.util.HashMap; import java.util.Map; -public class CompositeGeneratorLibrary implements Generator.GeneratorLibrary { +public class CompositeGeneratorLibrary implements Generator.Library { private Map generatorLibraries; - private Generator.GeneratorLibrary defaultLibrary = null; + private Generator.Library defaultLibrary = null; private static String LIBRARY_QUALIFIER_SEPARATOR = "::"; public CompositeGeneratorLibrary() { generatorLibraries = new HashMap(); } - public void addLibrary(String aQualifier, Generator.GeneratorLibrary aLibrary, boolean anIsDefault) { + public void addLibrary(String aQualifier, Generator.Library aLibrary, boolean anIsDefault) { if (anIsDefault || defaultLibrary == null) { defaultLibrary = aLibrary; } @@ -53,14 +53,14 @@ public class CompositeGeneratorLibrary implements Generator.GeneratorLibrary { String qualifier; String libraryName; int position; - Generator.GeneratorLibrary library; + Generator.Library library; position = anIdentifier.indexOf( LIBRARY_QUALIFIER_SEPARATOR ); if (position>=0) { libraryName = anIdentifier.substring(0, position); qualifier = anIdentifier.substring(position + LIBRARY_QUALIFIER_SEPARATOR.length()); - library = (Generator.GeneratorLibrary) generatorLibraries.get(libraryName); + library = (Generator.Library) generatorLibraries.get(libraryName); if (library==null) throw new GeneratorExc("CompositeGeneratorLibrary: library '"+libraryName+"' not found"); diff --git a/source/mir/generator/FreemarkerGenerator.java b/source/mir/generator/FreemarkerGenerator.java index c0ebb764..d4a4ee7b 100755 --- a/source/mir/generator/FreemarkerGenerator.java +++ b/source/mir/generator/FreemarkerGenerator.java @@ -30,19 +30,13 @@ package mir.generator; import java.io.PrintWriter; +import java.io.File; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Vector; - -import mir.log.LoggerWrapper; -import mir.util.GeneratorFormatAdapters; -import mir.util.RewindableIterator; - -import org.apache.commons.beanutils.MethodUtils; -import org.apache.commons.beanutils.PropertyUtils; import freemarker.template.FileTemplateCache; import freemarker.template.SimpleScalar; @@ -54,6 +48,11 @@ import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; import freemarker.template.TemplateModelRoot; import freemarker.template.TemplateScalarModel; +import mir.log.LoggerWrapper; +import mir.util.GeneratorFormatAdapters; +import mir.util.RewindableIterator; +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.beanutils.PropertyUtils; public class FreemarkerGenerator implements Generator { @@ -90,7 +89,7 @@ public class FreemarkerGenerator implements Generator { return new IteratorAdapter(anIterator); } - private static TemplateMethodModel makeFunctionAdapter(Generator.GeneratorFunction aFunction) { + private static TemplateMethodModel makeFunctionAdapter(Generator.Function aFunction) { return new FunctionAdapter(aFunction); } @@ -104,10 +103,10 @@ public class FreemarkerGenerator implements Generator { if (anObject instanceof TemplateModel) return (TemplateModel) anObject; - else if (anObject instanceof Generator.GeneratorFunction) - return makeFunctionAdapter((Generator.GeneratorFunction) anObject); + else if (anObject instanceof Generator.Function) + return makeFunctionAdapter((Generator.Function) anObject); else if (anObject instanceof Integer) - return makeStringAdapter(((Integer) anObject).toString()); + return makeStringAdapter(anObject.toString()); else if (anObject instanceof Boolean) { if (((Boolean) anObject).booleanValue()) return makeStringAdapter("1"); @@ -181,7 +180,7 @@ public class FreemarkerGenerator implements Generator { private IteratorAdapter(Iterator anIterator) { iterator = anIterator; - valuesCache = new Vector(); + valuesCache = new ArrayList(); position=0; @@ -249,7 +248,7 @@ public class FreemarkerGenerator implements Generator { private ListAdapter(List aList) { list = aList; - valuesCache = new Vector(); + valuesCache = new ArrayList(); position=0; } @@ -299,9 +298,9 @@ public class FreemarkerGenerator implements Generator { } private static class FunctionAdapter implements TemplateMethodModel { - private Generator.GeneratorFunction function; + private Generator.Function function; - public FunctionAdapter(Generator.GeneratorFunction aFunction) { + public FunctionAdapter(Generator.Function aFunction) { function = aFunction; } @@ -352,11 +351,11 @@ public class FreemarkerGenerator implements Generator { } } - public static class FreemarkerGeneratorLibrary implements GeneratorLibrary { + public static class FreemarkerGeneratorLibrary implements Library { private FileTemplateCache templateCache; - public FreemarkerGeneratorLibrary(String aTemplateRoot) { - templateCache = new FileTemplateCache( aTemplateRoot+"/" ); + public FreemarkerGeneratorLibrary(File aTemplateRoot) { + templateCache = new FileTemplateCache(aTemplateRoot); templateCache.setLoadingPolicy(FileTemplateCache.LOAD_ON_DEMAND); } @@ -371,15 +370,16 @@ public class FreemarkerGenerator implements Generator { } } - public static class FreemarkerGeneratorLibraryFactory implements GeneratorLibraryFactory { - private String basePath; + public static class FreemarkerGeneratorLibraryFactory implements LibraryFactory { + private File basePath; - public FreemarkerGeneratorLibraryFactory(String aBasePath) { + public FreemarkerGeneratorLibraryFactory(File aBasePath) { basePath = aBasePath; } - public GeneratorLibrary makeLibrary(String anInitializationString) { - return new FreemarkerGeneratorLibrary(basePath+anInitializationString); + public Library makeLibrary(String anInitializationString) { + // todo: the initialization string should be parsed + return new FreemarkerGeneratorLibrary(new File(basePath, anInitializationString)); }; } } diff --git a/source/mir/generator/Generator.java b/source/mir/generator/Generator.java index 3d46e47d..805d0ccc 100755 --- a/source/mir/generator/Generator.java +++ b/source/mir/generator/Generator.java @@ -37,22 +37,27 @@ import java.util.Map; import mir.log.LoggerWrapper; +/** + * Interface representing a "generator", typically a template engine/ + */ public interface Generator { public void generate(Object anOutputWriter, Map aValues, LoggerWrapper aLogger) throws GeneratorExc, GeneratorFailure; - public static interface GeneratorLibrary { + public static interface Library { public Generator makeGenerator(String anIdentifier) throws GeneratorExc, GeneratorFailure; } - public static interface GeneratorLibraryFactory { - public GeneratorLibrary makeLibrary(String anInitializationString) throws GeneratorExc, GeneratorFailure ; + public static interface LibraryFactory { + public Library makeLibrary(String anInitializationString) throws GeneratorExc, GeneratorFailure ; } - public static interface GeneratorFunction { + /** interface for a generator implementation independent function */ + public static interface Function { + /** performs the function with the given parameters */ public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure; } - public static interface GeneratorTransformer { + public static interface Transformer { public void perform(Reader aSource, PrintWriter anOutput) throws GeneratorExc, GeneratorFailure; } } diff --git a/source/mir/generator/GeneratorHelper.java b/source/mir/generator/GeneratorHelper.java index cfd49e04..298723dd 100755 --- a/source/mir/generator/GeneratorHelper.java +++ b/source/mir/generator/GeneratorHelper.java @@ -33,14 +33,15 @@ package mir.generator; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.ArrayList; +import java.util.List; import mir.entity.adapter.EntityIteratorAdapter; import mir.util.CachingRewindableIterator; -import mir.util.ResourceBundleGeneratorFunction; +import mir.bundle.Bundle; +import mir.util.generator.BundleGeneratorFunction; import mircoders.global.MirGlobal; -import org.apache.struts.util.MessageResources; - public class GeneratorHelper { @@ -49,47 +50,34 @@ public class GeneratorHelper { */ public static Map makeBasicGenerationData(Locale[] aLocales, String aBundle, String aDefaultBundle) throws GeneratorExc{ - try{ - Map result = new HashMap(); - MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(result); - - - Object languages = - new CachingRewindableIterator( - new EntityIteratorAdapter( "", "id", 30, - MirGlobal.localizer().dataModel().adapterModel(), "language")); + try { + Map result = new HashMap(); + MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(result); + + Object languages = new CachingRewindableIterator(new EntityIteratorAdapter("", "id", 30, MirGlobal.localizer().dataModel().adapterModel(), "language")); - Object topics = - new CachingRewindableIterator( - new EntityIteratorAdapter("", "id", 30, - MirGlobal.localizer().dataModel().adapterModel(), "topic")); + Object topics = new CachingRewindableIterator(new EntityIteratorAdapter("", "id", 30, MirGlobal.localizer().dataModel().adapterModel(), "topic")); - Object articleTypes = - new CachingRewindableIterator( - new EntityIteratorAdapter( "", "id", 30, - MirGlobal.localizer().dataModel().adapterModel(), "articleType")); + Object articleTypes = new CachingRewindableIterator(new EntityIteratorAdapter("", "id", 30, MirGlobal.localizer().dataModel().adapterModel(), "articleType")); - Object commentStatuses = - new CachingRewindableIterator( - new EntityIteratorAdapter( "", "id", 30, - MirGlobal.localizer().dataModel().adapterModel(), "commentStatus")); + Object commentStatuses = new CachingRewindableIterator(new EntityIteratorAdapter("", "id", 30, MirGlobal.localizer().dataModel().adapterModel(), "commentStatus")); result.put("commentstatuses", commentStatuses); result.put("articletypes", articleTypes); result.put("languages", languages); result.put("topics", topics); - - result.put( "lang", - new ResourceBundleGeneratorFunction( aLocales, - new MessageResources[] { MessageResources.getMessageResources(aBundle), - MessageResources.getMessageResources(aDefaultBundle)})); - + List bundles = new ArrayList(); + for (int i=0; iTitle:

- *

Description:

- *

Copyright: Copyright (c) 2003

- *

Company:

- * @author not attributable - * @version 1.0 - */ - private static class ContextAdapter implements Context { - public boolean containsKey(java.lang.Object key) { - return false; - } - - public Object get(java.lang.String key) { - return null; - } - - public Object[] getKeys() { - return new Object[] {}; - } - - public Object put(java.lang.String key, java.lang.Object value) { - return null; - } - - public Object remove(java.lang.Object key) { - return null; - } - } - - /** - * * @param aMap * @return */ @@ -166,7 +135,7 @@ public class VelocityGenerator implements Generator { * @param aFunction * @return */ - private static Object makeFunctionAdapter(Generator.GeneratorFunction aFunction) { + private static Object makeFunctionAdapter(Generator.Function aFunction) { return new FunctionAdapter(aFunction); } @@ -217,8 +186,8 @@ public class VelocityGenerator implements Generator { if (anObject instanceof Context) return anObject; - else if (anObject instanceof Generator.GeneratorFunction) - return makeFunctionAdapter((Generator.GeneratorFunction) anObject); + else if (anObject instanceof Generator.Function) + return makeFunctionAdapter((Generator.Function) anObject); else if (anObject instanceof Integer) return anObject; else if (anObject instanceof Boolean) @@ -249,13 +218,13 @@ public class VelocityGenerator implements Generator { * @version 1.0 */ public static class FunctionAdapter implements VelocityAdapter { - private GeneratorFunction function; + private Function function; public Object getOriginal() { return function; } - private FunctionAdapter(GeneratorFunction aFunction) { + private FunctionAdapter(Function aFunction) { function = aFunction; } @@ -364,14 +333,11 @@ public class VelocityGenerator implements Generator { private static class IteratorAdapter extends AbstractList implements VelocityAdapter { private Iterator iterator; private List valuesCache; - private int position; private IteratorAdapter(Iterator anIterator) { iterator = anIterator; valuesCache = new Vector(); - position=0; - if (iterator instanceof RewindableIterator) { ((RewindableIterator) iterator).rewind(); @@ -423,13 +389,11 @@ public class VelocityGenerator implements Generator { private static class ListAdapter extends AbstractList implements VelocityAdapter { private List list; private List valuesCache; - private int position; private ListAdapter(List aList) { list = aList; valuesCache = new Vector(); - position=0; } private void getUntil(int anIndex) { @@ -569,46 +533,22 @@ public class VelocityGenerator implements Generator { * @author not attributable * @version 1.0 */ - public static class VelocityGeneratorLibrary implements GeneratorLibrary { + public static class VelocityGeneratorLibrary implements Library { private VelocityEngine engine; - public VelocityGeneratorLibrary(String aTemplateRoot) throws GeneratorExc, GeneratorFailure { + public VelocityGeneratorLibrary(File aTemplateRoot) throws GeneratorExc, GeneratorFailure { try { engine = new VelocityEngine(); try { engine.setProperty(VelocityEngine.RESOURCE_LOADER, "file"); - } - catch (Throwable t) { - logger.error(VelocityEngine.RESOURCE_LOADER); - } - - try { engine.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); - } - catch (Throwable t) { - logger.error("file.resource.loader.class"); - } - - try { - engine.setProperty("file.resource.loader.path", aTemplateRoot); - } - catch (Throwable t) { - logger.error("file.resource.loader.path"); - - } - try { + engine.setProperty("file.resource.loader.path", aTemplateRoot.getAbsolutePath()); engine.setProperty("file.resource.loader.cache", "true"); } catch (Throwable t) { - logger.error("file.resource.loader.cache"); - - } - try { - engine.setProperty("file.resource.loader.modificationCheckInterval", "10"); - } - catch (Throwable t) { - logger.error("file.resource.loader.modificationCheckInterval"); + logger.error("Error while constructing library: " + t.toString()); + throw new GeneratorFailure(t); } try { @@ -642,15 +582,15 @@ public class VelocityGenerator implements Generator { * @author not attributable * @version 1.0 */ - public static class VelocityGeneratorLibraryFactory implements GeneratorLibraryFactory { - private String basePath; + public static class VelocityGeneratorLibraryFactory implements LibraryFactory { + private File basePath; - public VelocityGeneratorLibraryFactory(String aBasePath) { + public VelocityGeneratorLibraryFactory(File aBasePath) { basePath = aBasePath; } - public GeneratorLibrary makeLibrary(String anInitializationString) throws GeneratorExc, GeneratorFailure { - return new VelocityGeneratorLibrary(basePath+anInitializationString); + public Library makeLibrary(String anInitializationString) throws GeneratorExc, GeneratorFailure { + return new VelocityGeneratorLibrary(new File(basePath, anInitializationString)); }; } } diff --git a/source/mir/generator/tal/CachingFileLoader.java b/source/mir/generator/tal/CachingFileLoader.java index df0c2b6a..c9f042b9 100755 --- a/source/mir/generator/tal/CachingFileLoader.java +++ b/source/mir/generator/tal/CachingFileLoader.java @@ -35,10 +35,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; public class CachingFileLoader { private Map cachedObjects; @@ -49,7 +49,7 @@ public class CachingFileLoader { public CachingFileLoader(int aCapacity, CachedFileObjectFactory aFactory) { capacity = aCapacity; cachedObjects = new HashMap(); - history = new Vector(); + history = new ArrayList(); factory = aFactory; } diff --git a/source/mir/generator/tal/MirExpressionParser.java b/source/mir/generator/tal/MirExpressionParser.java index 3d10c60c..3413fc5d 100755 --- a/source/mir/generator/tal/MirExpressionParser.java +++ b/source/mir/generator/tal/MirExpressionParser.java @@ -143,4 +143,12 @@ public class MirExpressionParser implements TALExpressionParser { } } + public Object evaluatePseudoVariable(Object aContext, String aName) { + try { + return ParameterExpander.getObjectField(aContext, aName); + } + catch (Throwable t) { + throw new TALFailure(t); + } + } } \ No newline at end of file diff --git a/source/mir/generator/tal/SimpleTemplateNodeLibraryRegistry.java b/source/mir/generator/tal/SimpleTemplateNodeLibraryRegistry.java new file mode 100755 index 00000000..561f50a4 --- /dev/null +++ b/source/mir/generator/tal/SimpleTemplateNodeLibraryRegistry.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with any library licensed under the Apache Software License, + * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library + * (or with modified versions of the above that use the same license as the above), + * and distribute linked combinations including the two. You must obey the + * GNU General Public License in all respects for all of the code used other than + * the above mentioned libraries. If you modify this file, you may extend this + * exception to your version of the file, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your version. + */ +package mir.generator.tal; + +import java.util.Map; +import java.util.HashMap; + +import mir.generator.tal.template.TemplateNodeLibraryRegistry; +import mir.generator.tal.template.TemplateNodeLibrary; + +public class SimpleTemplateNodeLibraryRegistry implements TemplateNodeLibraryRegistry { + private Map urlToLibrary; + private Map prefixToLibrary; + + public SimpleTemplateNodeLibraryRegistry() { + urlToLibrary = new HashMap(); + prefixToLibrary = new HashMap(); + } + + public void registerTemplateNodeLibrary(String aPrefix, String aUrl, TemplateNodeLibrary aLibrary) { + urlToLibrary.put(aUrl, aLibrary); + prefixToLibrary.put(aPrefix, aLibrary); + } + + public TemplateNodeLibrary findLibraryForUrl(String aUrl) { + return (TemplateNodeLibrary) urlToLibrary.get(aUrl); + } + + public TemplateNodeLibrary findLibraryForPrefix(String aPrefix) { + return (TemplateNodeLibrary) prefixToLibrary.get(aPrefix); + } +} diff --git a/source/mir/generator/tal/TALTemplateEngine.java b/source/mir/generator/tal/TALTemplateEngine.java index 071d333a..aa3fb763 100755 --- a/source/mir/generator/tal/TALTemplateEngine.java +++ b/source/mir/generator/tal/TALTemplateEngine.java @@ -34,59 +34,79 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Map; -import java.util.HashMap; +import java.util.List; import mir.generator.tal.interfaces.TALExpressionParser; -import mir.generator.tal.template.TALTemplate; -import mir.generator.tal.template.TALTemplateNodeLibrary; -import mir.generator.tal.template.TALBasicTemplateNodeLibrary; +import mir.generator.tal.template.*; +import mir.util.StringRoutines; -public class TALTemplateEngine { +public class TALTemplateEngine implements TemplateLibrary { private TALExpressionParser expressionParser; - private String basePath; + private File basePath; private CachingFileLoader loader; - private Map urlToLibrary; - private Map prefixToLibrary; + private SimpleTemplateNodeLibraryRegistry registry; - public TALTemplateEngine(TALExpressionParser anExpressionParser, String aBasePath) { + public TALTemplateEngine(TALExpressionParser anExpressionParser, File aBasePath) { expressionParser = anExpressionParser; basePath = aBasePath; loader = new CachingFileLoader(100, new TemplateFactory()); - urlToLibrary = new HashMap(); - prefixToLibrary = new HashMap(); + registry = new SimpleTemplateNodeLibraryRegistry(); - registerTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal", new TALBasicTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal")); + registerTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal", + new CoreTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal")); registerTemplateNodeLibrary("metal", "http://xml.zope.org/namespaces/metal", - new TALBasicTemplateNodeLibrary("metal", "http://xml.zope.org/namespaces/metal")); - + new MacroTemplateNodeLibrary("metal", "http://xml.zope.org/namespaces/metal")); } - public void registerTemplateNodeLibrary(String aPrefix, String aUrl, TALTemplateNodeLibrary aLibrary) { - urlToLibrary.put(aUrl, aLibrary); - prefixToLibrary.put(aPrefix, aLibrary); + public void registerTemplateNodeLibrary(String aPrefix, String aUrl, TemplateNodeLibrary aLibrary) { + registry.registerTemplateNodeLibrary(aPrefix, aUrl, aLibrary); } - public TALTemplate loadTemplate(String aName) throws IOException { - File location = new File(basePath, aName); - return (TALTemplate) loader.retrieveFile(location.getCanonicalPath()); - } + public Template loadTemplate(String aName) throws IOException, TemplateProcessingException { + List parts = StringRoutines.splitString(aName, "#"); + + if (parts.size()!=1 && parts.size()!=2) { + throw new TemplateProcessingException("Invalid template name: " + aName); + } + + File location = new File(basePath, (String) parts.get(0)); + + Template baseTemplate = (Template) loader.retrieveFile(location.getCanonicalPath()); + + if (baseTemplate!=null && parts.size()>1) { + Map definitions = (Map) baseTemplate.getContext().get(MacroTemplateNodeLibrary.MACRO_DEFINITIONS_KEY); + if (definitions==null || !definitions.containsKey(parts.get(1))) { + throw new TemplateProcessingException("No macro '"+(String) parts.get(1)+"' found in template '" + (String) parts.get(0) + "'"); + } - public TALTemplateNodeLibrary getLibraryForPrefix(String aPrefix) { - return (TALTemplateNodeLibrary) prefixToLibrary.get(aPrefix); + return new Template(expressionParser, (TemplateNode) definitions.get(parts.get(1)), baseTemplate.getContext()); + } + else { + return baseTemplate; + } + + + +// public Template(TALExpressionParser aParser, TemplateNode aRootNode, Map aTemplateContext) { } - public TALTemplateNodeLibrary getLibraryForUrl(String aUrl) { - return (TALTemplateNodeLibrary) urlToLibrary.get(aUrl); + public Template lookupTemplate(String aName) throws TemplateProcessingException { + try { + return loadTemplate(aName); + } + catch (IOException e) { + throw new TemplateProcessingException("Can't load template " + aName + ": " + e.toString(), e); + } } private class TemplateFactory implements CachingFileLoader.CachedFileObjectFactory { public Object constructObject(InputStream aStream) { try { - TALTemplateParser parser = new TALTemplateParser(TALTemplateEngine.this); + TALTemplateParser parser = new TALTemplateParser(registry); - return parser .parse(aStream, expressionParser); + return parser.parse(aStream, expressionParser); } catch (Throwable t) { throw new TALFailure(t); diff --git a/source/mir/generator/tal/TALTemplateParser.java b/source/mir/generator/tal/TALTemplateParser.java index d37f95f2..ff1596f5 100755 --- a/source/mir/generator/tal/TALTemplateParser.java +++ b/source/mir/generator/tal/TALTemplateParser.java @@ -39,13 +39,15 @@ import java.io.Reader; import java.io.StringReader; import java.util.Iterator; import java.util.Map; +import java.util.HashMap; import mir.generator.tal.interfaces.TALExpressionParser; import mir.generator.tal.template.CompositeTemplateNode; import mir.generator.tal.template.PlainTextTemplateNode; -import mir.generator.tal.template.TALTemplate; -import mir.generator.tal.template.TALTemplateNodeLibrary; +import mir.generator.tal.template.Template; +import mir.generator.tal.template.TemplateNodeLibrary; import mir.generator.tal.template.TemplateNode; +import mir.generator.tal.template.TemplateNodeLibraryRegistry; import mir.util.HTMLRoutines; import mir.util.xml.SectionHandler; import mir.util.xml.XMLName; @@ -54,21 +56,18 @@ import mir.util.xml.XMLParserExc; import mir.util.xml.XMLParserFailure; import mir.util.xml.XMLReaderTool; -// TODO: add a templatelibrary repository and remove dependency of TALTemplateEngine - public class TALTemplateParser { - private TALTemplateEngine engine; + private TemplateNodeLibraryRegistry registry; - //private static final String TAL_PREFIX = "tal"; - public TALTemplateParser(TALTemplateEngine anEngine) { - engine = anEngine; + public TALTemplateParser(TemplateNodeLibraryRegistry aRegistry) { + registry = aRegistry; } - public TALTemplate parse(String aData, TALExpressionParser aParser) throws TALExc, TALFailure { + public Template parse(String aData, TALExpressionParser aParser) throws TALExc, TALFailure { return parse(new StringReader(aData), aParser); } - public TALTemplate parse(File aFile, TALExpressionParser aParser) throws TALExc, TALFailure { + public Template parse(File aFile, TALExpressionParser aParser) throws TALExc, TALFailure { try { return parse(new BufferedInputStream(new FileInputStream(aFile), 1024*128), aParser); } @@ -76,12 +75,13 @@ public class TALTemplateParser { throw new TALFailure(e); } } - public TALTemplate parse(InputStream anInputStream, TALExpressionParser aParser) throws TALExc, TALFailure { + public Template parse(InputStream anInputStream, TALExpressionParser aParser) throws TALExc, TALFailure { return parse(new InputStreamReader(anInputStream), aParser); } - public TALTemplate parse(Reader aReader, TALExpressionParser aParser) throws TALExc, TALFailure { - TALHandler handler = new TALHandler(aParser); + public Template parse(Reader aReader, TALExpressionParser aParser) throws TALExc, TALFailure { + Map templateContext = new HashMap(); + TALHandler handler = new TALHandler(aParser, templateContext); try { XMLParserEngine.getInstance().parse("html", aReader, handler); @@ -90,28 +90,33 @@ public class TALTemplateParser { throw new TALFailure(e); } - return new TALTemplate(aParser, handler.getNode()); + return new Template(aParser, handler.getNode(), templateContext); } protected class TALHandler implements SectionHandler { private CompositeTemplateNode compositeNode; private StringBuffer data; + private StringBuffer plainData; private TALExpressionParser parser; private String currentTag; - private TALTemplateNodeLibrary library; + private TemplateNodeLibrary library; private XMLName tag; private Map attributes; + private Map templateContext; - public TALHandler(TALExpressionParser aParser) { + public TALHandler(TALExpressionParser aParser, Map aTemplateContext) { parser = aParser; data = new StringBuffer(); + plainData = new StringBuffer(); compositeNode = new CompositeTemplateNode(); + templateContext = aTemplateContext; } private void flushData() { if (data.length()!=0) { - compositeNode.appendSubNode(new PlainTextTemplateNode(data.toString())); + compositeNode.appendSubNode(new PlainTextTemplateNode(data.toString(), plainData.toString())); data.delete(0, data.length()); + plainData.delete(0, plainData.length()); } } @@ -119,15 +124,15 @@ public class TALTemplateParser { appendCode(anExtraData); } - public TALTemplateNodeLibrary findLibrary(XMLName aName) { - TALTemplateNodeLibrary result = null; + public TemplateNodeLibrary findLibrary(XMLName aName) { + TemplateNodeLibrary result = null; if (aName.getNamespaceURI()!=null) { - result = engine.getLibraryForUrl(aName.getNamespaceURI()); + result = registry.findLibraryForUrl(aName.getNamespaceURI()); } if ((result == null) && (aName.getPrefix()!=null) && (aName.getPrefix().length()>0)) { - result = engine.getLibraryForPrefix(aName.getPrefix()); + result = registry.findLibraryForPrefix(aName.getPrefix()); } return result; @@ -155,23 +160,31 @@ public class TALTemplateParser { appendText((String) entry.getValue()); appendCode("\""); } - appendCode(">"); } else { tag = aTag; attributes = anAttributes; } - return new TALHandler(parser); + return new TALHandler(parser, templateContext); }; public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc { if (library == null) { - appendSubNode(((TALHandler) aHandler).getNode()); - appendCode(""); + TemplateNode subNode = ((TALHandler) aHandler).getNode(); + if (subNode instanceof CompositeTemplateNode && + ((CompositeTemplateNode) subNode).isEmpty()) { + appendCode(" />"); + } + else { + appendCode(">"); + appendSubNode(subNode); + appendCode(""); + } } else { - appendSubNode(library.constructTemplateNode(parser, tag, attributes, ((TALHandler) aHandler).getNode())); + appendSubNode( + library.constructTemplateNode(parser, tag, attributes, ((TALHandler) aHandler).getNode(), templateContext)); tag = null; attributes = null; } @@ -189,6 +202,7 @@ public class TALTemplateParser { protected void appendText(String aText) { data.append(HTMLRoutines.encodeHTML(aText)); + plainData.append(aText); } public void finishSection() throws XMLParserExc { diff --git a/source/mir/generator/tal/TALTest.java b/source/mir/generator/tal/TALTest.java index 88be8640..1eb475d4 100755 --- a/source/mir/generator/tal/TALTest.java +++ b/source/mir/generator/tal/TALTest.java @@ -31,28 +31,79 @@ package mir.generator.tal; import java.io.PrintWriter; +import java.io.File; import java.util.HashMap; import java.util.Map; import mir.generator.tal.interfaces.TALLogger; -import mir.generator.tal.template.TALTemplate; -import mir.util.HTMLRoutines; +import mir.generator.tal.template.Template; +import mir.generator.tal.template.TemplateLibrary; +import mir.generator.tal.template.TemplateProcessingException; +import mir.generator.tal.template.CoreTemplateNodeLibrary; +import mir.generator.tal.template.MacroTemplateNodeLibrary; public class TALTest { public static void main(String args[]) { try { - System.out.println(HTMLRoutines.resolveHTMLEntites("ééad&a;&aaddsd&#;é&&sdf&f;éaap")); + final SimpleTemplateNodeLibraryRegistry registry = new SimpleTemplateNodeLibraryRegistry(); - TALTemplateEngine engine = new TALTemplateEngine(new MirExpressionParser(), "m:/biotechdev/mir/etc/producertal/"); + registry.registerTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal", + new CoreTemplateNodeLibrary("tal", "http://xml.zope.org/namespaces/tal")); + registry.registerTemplateNodeLibrary("metal", "http://xml.zope.org/namespaces/metal", + new MacroTemplateNodeLibrary("metal", "http://xml.zope.org/namespaces/metal")); + + TemplateLibrary library = new TemplateLibrary() { + public Template lookupTemplate(String aTemplateName) throws TemplateProcessingException { + try { + TALTemplateParser parser = new TALTemplateParser(registry); + + if (aTemplateName.equals("a")) { + return parser.parse("

bla - ${lang("delete")} + ${lang("delete")} | @@ -90,21 +90,22 @@ extra navigation - +

- [+] ${lang("add")}   - [<] ${lang("back")}   - [<<<] ${lang("head.start")} + + [+] ${lang("add")}   + + [<] ${lang("back")}   + [<<<] ${lang("head.start")}

- +

[+] ${lang("add")}   - [<] ${lang("back")}   - [<<<] ${lang("head.start")} + [<] ${lang("back")}  

@@ -312,6 +313,7 @@
>${lang("contentsearch.field.contents")} +
class="listrow2"> @@ -410,15 +412,15 @@ functions to show media for an article/comment edit page - - + + - - + + - + @@ -440,19 +442,20 @@ - [+] ${lang("content.addimage")} | - ${lang("content.uploadimage")} + [+] ${lang("content.addimage")} | + ${lang("content.uploadimage")}
- edit  + edit  - [-] ${lang("delete")} + [-] ${lang("deattach")} | + ${lang("edit")}
- [+] ${lang("content.addaudio")} | - ${lang("content.uploadaudio")} + [+] ${lang("content.addaudio")} | + ${lang("content.uploadaudio")}
- edit  + edit  - [-] ${lang("delete")} + [-] ${lang("deattach")} | + ${lang("edit")}
- [+] ${lang("content.addvideo")} | - ${lang("content.uploadvideo")} + [+] ${lang("content.addvideo")} | + ${lang("content.uploadvideo")}
- edit  + edit  - [-] ${lang("delete")} + [-] ${lang("deattach")} | + ${lang("edit")}
- [+] ${lang("content.addother")} | - ${lang("content.uploadother")} + [+] ${lang("content.addother")} | + ${lang("content.uploadother")}
- edit  + edit  - [-] ${lang("delete")} + [-] ${lang("deattach")} | + ${lang("edit")}
- + + + + + +

${lang("no_matches_found")}

diff --git a/templates/admin/comment.template b/templates/admin/comment.template index 6b1c7a68..1fecf8eb 100755 --- a/templates/admin/comment.template +++ b/templates/admin/comment.template @@ -29,9 +29,11 @@ + + @@ -110,7 +112,7 @@
- +
diff --git a/templates/admin/commentlist.template b/templates/admin/commentlist.template index 38ec7265..426dc01a 100755 --- a/templates/admin/commentlist.template +++ b/templates/admin/commentlist.template @@ -37,6 +37,7 @@ +
@@ -128,9 +129,6 @@ ${lang("edit")} | - - ${lang("start.show")} - | ${lang("commentlist.allcomments")} @@ -141,14 +139,13 @@ ${entry.title} (${entry.id})  - ${lang("by")}: ${entry.creator} + ${lang("by")}: ${utility.encodeHTML(entry.creator)}
- ${utility.prettyEncodeHTML(entry.description)} + ${utility.prettyEncodeHTML(utility.subString(entry.description, 0, config["Mir.Admin.ListTextLengthLimit"]))} -
URL: ${entry.main_url}
+
URL: ${utility.encodeHTML(entry.main_url)}

- [ ${lang("comment.operation."+op)} ] @@ -168,8 +165,8 @@  |  - ${lang("edit")} - + ${lang("edit")} + IMAGES
diff --git a/templates/admin/content.template b/templates/admin/content.template index c75de475..dfe72e56 100755 --- a/templates/admin/content.template +++ b/templates/admin/content.template @@ -16,6 +16,12 @@ + + + + @@ -253,7 +259,7 @@
- + diff --git a/templates/admin/contentlist.template b/templates/admin/contentlist.template index 107a4c4f..b89e0aa1 100755 --- a/templates/admin/contentlist.template +++ b/templates/admin/contentlist.template @@ -94,7 +94,7 @@ | ${lang("edit")} | - ${lang("preview")} | + ${lang("preview")} | ${lang("contentlist.comments")} (${entry.commentcount}) diff --git a/templates/admin/mediatypelist.template b/templates/admin/mediatypelist.template index ba647425..2a9996d7 100755 --- a/templates/admin/mediatypelist.template +++ b/templates/admin/mediatypelist.template @@ -12,7 +12,7 @@ - + diff --git a/templates/admin/start_admin.template b/templates/admin/start_admin.template index 958b6c91..145ef36f 100755 --- a/templates/admin/start_admin.template +++ b/templates/admin/start_admin.template @@ -27,7 +27,6 @@

> ${lang("start.content.not_published")}
- > ${lang("start.content.with_media")}
> ${lang("start.content.last_changes")}
> ${lang("start.content.with_comments")}

diff --git a/templates/admin/superusermenu.template b/templates/admin/superusermenu.template index 36d0305f..e6909018 100755 --- a/templates/admin/superusermenu.template +++ b/templates/admin/superusermenu.template @@ -21,6 +21,7 @@ > ${lang("superusermenu.users")}
> ${lang("superusermenu.languages")}
> ${lang("superusermenu.abuse")}
+ > ${lang("superusermenu.reload")}

  diff --git a/web/produced/img/arrow_down.gif b/web/produced/img/arrow_down.gif deleted file mode 100755 index b2b5e2f3ae26c4c6c900a75c5a55150888f58aba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65 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 TOnPI|8sOL@0Dyn*D_1hR-kwbr*57zY$|5v z!Mi1z4#{*LZ<&@mG$iM|H30AcR0_evFlGRQ?ZM)E@FpE5_f*=3@wOak3|393!F%SR<@cxwe^n~IJs4R=& zZQ)*enm3sgO|wym4-S&>ki^cC6uY-6t1(<(Hb*jDmzaCdY(0NN@Rm1H;-0=PLM)5` z!Hh`ZIZ&vMg%wWJ<6IIE3qfW~6I@*$`9w=gwHUzWw#~e=6^=6UsU{p!Q`f-ZQaUTB z6j=({&bSsb-C@>cMNj-D zv9`-q&r}`? zcA42G;GlNg{q85VQ;BI1%(~uLLzpWo>G-h0e=syNb6R5KUGJKr)UlyFZ^pEGI8*2U zLb70kldjZ78xba^U2-%fmDdjCFJq@3%zqi_wnSbLUBD5-pygQ0&>X(hs^FtAJYhnP z%6H3eFM4R4n&@+lcP53amxH_;RPT#LoqfwgF1@SIH%?@o8$09PK7mlWYPv7<64y&; z(#4=%yBs3g8oiEH<10qoX9IUD7|zpD2{ZmjjJ-@GOOPCU;c}|jzdFOgSviH>@dy9eNL8IKaa^JO=uiC#S?`)r;GEB8Esn{$;d zUgYn*Y+uP^lbWW@r}d?>)5GOX*cwX&k<$n@2YZbe{Vus zo4Bl;ugw@|Jlsvyh-g=xE~VU`BwnvpcHIgYfTO))hkn|eyx2ZgAjnMY7ofy4LcBJ8 zX!d$cz{PX+Cw(7pTW2YDjJR!#zOtHN9M0v37&m;^8!cSHlNS_E$uN2$2 YNZ@yyFNcHm$jX~F*-o@b7Yabozk+Yt^#A|> diff --git a/web/produced/img/dot.gif b/web/produced/img/dot.gif deleted file mode 100755 index d80b7f485da765d6ae3d75a75576451cf1a49bdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67 zcmZ?wbhEHbv7_0#Wdk}U2 diff --git a/web/produced/img/extlink.gif b/web/produced/img/extlink.gif deleted file mode 100755 index 4366ee65fd5b2de6ee3f892d83bd16790a104c52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmZ?wbhEHbro6ncyWND%bDpBB7=twc$TbrT diff --git a/web/produced/img/help.gif b/web/produced/img/help.gif deleted file mode 100755 index f177ee298e02896e72c942f0ace897060072a803..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 zcmZ?wbhEHb6ky7ro;`Turd3z-)k8~N7#OSpappNe diff --git a/web/produced/img/intlink.gif b/web/produced/img/intlink.gif deleted file mode 100755 index bc10b45a2bed3c6b9087f2dd821a448e26a84ba3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb*&M+`ADE?$&WME)o&;hc6vfMzn?3{kJ(`%R( diSTL=~LK!>f3|j WGm*uGR-cL@T|<=fl3Tb~8LR*b}yaE5!F>5_h24A)o+ z_T+MHkWtV|RN^`4=g=v@P{4R{O;Ckk$NG~B(RR;;cYd^c8!j@ zh`mF#rbnA*Mu|JK3&+0Nqw^&DL*&M+`ADE?$&WME)o&;ha;K=KSsigWsvnY5oN irM!)-Y}}XibzSCsqejJ-OVf;9`(LV_4B}*Eum%8@Mi~+Z^fq{cT z2Pnw^GJ}C-zQ9S()q5?Pc{lAppe%PcJ@9V7We==tTS7w)-mUh-+n=;W`t2u%voi|n5rR0>n`uRsUr&9T=ra=>C6`g;W z@4yilWmVWv-(*=WTUVZ9>(J6uF`=V(Qgu|{^og3Y^yU=JSTMV6`jT0_b;VO8p>SJv@UEbPheQM!tO1XRVH*Gd diff --git a/web/produced/img/photo_small.gif b/web/produced/img/photo_small.gif deleted file mode 100755 index 5f1796ce1ac289dc875a31f825bae784129304ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 860 zcmZ8gZAg<*6h3zjnK_0_Fn_$2j(#i%1q;lAn&H-mqed1I4bq^kfru?7!D=n0NrFXC zjB>Gx{)`G4L4iNs2@2~^O^|}1AALX(L`8#lR#eaP4iP$V-t*k&o^$TK=bU%GU4l@AYqPY3lI% zxoedpsukM-+$D)v=3NASGh^ua=P4m3e`c4V%g%i=<&7-*(0<%A;Me45LM+#2hiRyTcY0>cJgzm&*6#Fg$yRdm#tn z&2ue}44n;6yh0C}Kr8GRLWYuxvO*54Rb%OxZ1t2W6)M6B7(^45+7HIe3p4+JEhu?q+aiiqTK z@Uo;tva$1WR&nxj2??;&M|M_MvGOP?@^cqO3Ny2?vT|~W&F5wmPL)-XWLd=}CRxD0 zQC@~wiG`hoDVbj=QdVA0Rz`{OJR9$Z6Q|BdGjQ?TDn5By<~mog^WAGV9yv2eKYjSz UiRa~mw=VCWefrGv&5^+x0GhmVg#Z8m diff --git a/web/produced/img/sp.gif b/web/produced/img/sp.gif deleted file mode 100755 index 35d42e808f0a8017b8d52a06be2f8fec0b466a66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43 scmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE7Dgb&paUX6G7L;iE{qJ;0LZEa`2YX_ diff --git a/web/produced/img/text_big.gif b/web/produced/img/text_big.gif deleted file mode 100755 index 2a31faaa73a442c558b0b8d888e4f8f0d08fd905..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmZ?wbhEHb6k!l!IK%(~`u_g^|Nk#&n6Q8Uey{+DQ2fcl$iTqDpabH7)G{!~N$lG5 zWde)i>bZ*hGOf=GUJq5;(R-b>(BXBEgTQ%puHAXP+pj&~Z_Q%clc9BQUn5!``SOWl!S~)BL diff --git a/web/produced/img/text_small.gif b/web/produced/img/text_small.gif deleted file mode 100755 index ec24bd6c9e312b19229b07e0d4cd4b5cb6a03cf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76 zcmZ?wbhEHb+Z^fq{cT z2Pnw^GJ}C-r+_EtDpupyXAe5Nw}r;6tUT_jB$qaA#rHE`lvlrB^6sj7>&iK6+_p5T zwLds^=+jJtlPiKuq-*6oS-u_jdK4i(OO)kI+pdO;h(DZFJDwX`+}?6EX3esi;A^4% zl_FKqQR%LVnT<_N`GF~lc7?IQjvc-+9#K*qaX}Ty)Fzw@ook(C7Vm$?d#&ZR;A^L@Y8%|t7i6#o0A>Vi Ak^lez diff --git a/web/produced/img/video_small.gif b/web/produced/img/video_small.gif deleted file mode 100755 index d61cd2927d8e7263ae6696c04b7a877666bd2f65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64 zcmZ?wbhEHb - - - - - diff --git a/web/produced/style/mir.css b/web/produced/style/mir.css deleted file mode 100755 index 6c12b856..00000000 --- a/web/produced/style/mir.css +++ /dev/null @@ -1,5 +0,0 @@ -a { color: #0000CC; text-decoration: underline} -a:hover { color: #333333; text-decoration: none} -td { font-family: "Times New Roman", Times, serif} -.small { font-size: x-small} -pre { font-family: "Courier", Courier, serif} -- 2.11.0