Merge lp:~slub.team/goobi-production/mq-interface-to-create-and-finalise-processes into lp:goobi-production/1.8
- mq-interface-to-create-and-finalise-processes
- Merge into 1.8
Proposed by
Ralf Claussnitzer
Status: | Merged |
---|---|
Merged at revision: | 82 |
Proposed branch: | lp:~slub.team/goobi-production/mq-interface-to-create-and-finalise-processes |
Merge into: | lp:goobi-production/1.8 |
Diff against target: |
2000 lines (+1629/-93) 20 files modified
WEB-INF/web.xml (+5/-0) config/GoobiConfig.properties (+35/-0) doc/implementing_active_mq_web_services_for_goobi.txt (+80/-0) doc/web_service_to_create_new_processes.txt (+104/-0) src-dubious/dubious/sub/goobi/helper/Page.java (+1/-1) src/de/sub/goobi/config/ConfigMain.java (+14/-19) src/de/sub/goobi/config/DigitalCollections.java (+77/-0) src/de/sub/goobi/forms/AktuelleSchritteForm.java (+1/-1) src/de/sub/goobi/forms/ProzesskopieForm.java (+10/-32) src/de/sub/goobi/helper/Helper.java (+54/-34) src/de/sub/goobi/helper/UghHelper.java (+15/-4) src/de/sub/goobi/helper/WebDav.java (+2/-1) src/de/sub/goobi/helper/enums/ReportLevel.java (+36/-0) src/org/goobi/mq/ActiveMQDirector.java (+231/-0) src/org/goobi/mq/ActiveMQProcessor.java (+161/-0) src/org/goobi/mq/MapMessageObjectReader.java (+242/-0) src/org/goobi/mq/WebServiceResult.java (+88/-0) src/org/goobi/mq/processors/CreateNewProcessProcessor.java (+375/-0) src/org/goobi/mq/processors/FinaliseStepProcessor.java (+97/-0) src/org/goobi/production/flow/statistics/hibernate/FilterHelper.java (+1/-1) |
To merge this branch: | bzr merge lp:~slub.team/goobi-production/mq-interface-to-create-and-finalise-processes |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ralf Claussnitzer (community) | Approve | ||
Review via email: mp+117031@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Ralf Claussnitzer (ralf-claussnitzer-deactivatedaccount) : | # |
review:
Approve
- 98. By Ralf Claussnitzer
-
add missing license header
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'WEB-INF/web.xml' | |||
2 | --- WEB-INF/web.xml 2012-04-20 06:57:46 +0000 | |||
3 | +++ WEB-INF/web.xml 2012-07-27 10:58:19 +0000 | |||
4 | @@ -215,6 +215,11 @@ | |||
5 | 215 | <listener-class>org.goobi.production.ImageIOInitializer</listener-class> | 215 | <listener-class>org.goobi.production.ImageIOInitializer</listener-class> |
6 | 216 | </listener> | 216 | </listener> |
7 | 217 | 217 | ||
8 | 218 | <!-- Listener to run ActiveMQ services --> | ||
9 | 219 | <listener> | ||
10 | 220 | <listener-class>org.goobi.mq.ActiveMQDirector</listener-class> | ||
11 | 221 | </listener> | ||
12 | 222 | |||
13 | 218 | <!-- | 223 | <!-- |
14 | 219 | xml-Rpc-Server starten <listener> <listener-class> | 224 | xml-Rpc-Server starten <listener> <listener-class> |
15 | 220 | de.sub.goobi.XmlRpc.Listener </listener-class> </listener> | 225 | de.sub.goobi.XmlRpc.Listener </listener-class> </listener> |
16 | 221 | 226 | ||
17 | === modified file 'config/GoobiConfig.properties' | |||
18 | --- config/GoobiConfig.properties 2012-07-05 13:00:48 +0000 | |||
19 | +++ config/GoobiConfig.properties 2012-07-27 10:58:19 +0000 | |||
20 | @@ -184,6 +184,41 @@ | |||
21 | 184 | # Password encryption SHA or MD5 | 184 | # Password encryption SHA or MD5 |
22 | 185 | ldap_encryption=SHA | 185 | ldap_encryption=SHA |
23 | 186 | 186 | ||
24 | 187 | # ----------------------------------- | ||
25 | 188 | # ActiveMQ web services | ||
26 | 189 | # ----------------------------------- | ||
27 | 190 | |||
28 | 191 | # If you want to use Goobi's ActiveMQ web servic interface, set the host here | ||
29 | 192 | #activeMQ.hostURL=tcp://localhost:61616 | ||
30 | 193 | |||
31 | 194 | # You can provide a topic that Goobi reports results and status messages to | ||
32 | 195 | #activeMQ.results.topic=GoobiProduction.ResultMessages.Topic | ||
33 | 196 | |||
34 | 197 | # By default, Goobi instructs the server to keep status messages for a | ||
35 | 198 | # equivalent of 7 days. You can change this value in (milliseconds to) meet | ||
36 | 199 | # your needs. 0 will disable the deletion of messages completely. (However, | ||
37 | 200 | # the messages will only available on the Active MQ server if your | ||
38 | 201 | # TopicSubscriber is online with the Active MQ server before the message is | ||
39 | 202 | # sent. You migth therefore consider to configure the timeToLive for offline | ||
40 | 203 | # usage within the Active MQ server’s activemq.xml file by adding a | ||
41 | 204 | # | ||
42 | 205 | # <policyEntry topic="GoobiProduction.ResultMessages.Topic"> | ||
43 | 206 | # <subscriptionRecoveryPolicy> | ||
44 | 207 | # <timedSubscriptionRecoveryPolicy recoverDuration="604800000" /> | ||
45 | 208 | # </subscriptionRecoveryPolicy> | ||
46 | 209 | # </policyEntry> | ||
47 | 210 | # | ||
48 | 211 | # block inside the <policyEntries>-Element. “recoverDuration” has to be given | ||
49 | 212 | # in milliseconds here, too.) | ||
50 | 213 | #activeMQ.results.timeToLive=604800000 | ||
51 | 214 | |||
52 | 215 | # You can provide a queue from which messages are read to create new processes | ||
53 | 216 | #activeMQ.createNewProcess.queue=GoobiProduction.CreateNewProcesses.Queue | ||
54 | 217 | |||
55 | 218 | # You can provide a queue from which messages are read to finalise steps | ||
56 | 219 | #activeMQ.finaliseStep.queue=GoobiProduction.FinaliseStep.Queue | ||
57 | 220 | |||
58 | 221 | |||
59 | 187 | ################################## | 222 | ################################## |
60 | 188 | # DO NOT CHANGE THE OPTIONS BELOW! | 223 | # DO NOT CHANGE THE OPTIONS BELOW! |
61 | 189 | ################################## | 224 | ################################## |
62 | 190 | 225 | ||
63 | === added directory 'doc' | |||
64 | === added file 'doc/implementing_active_mq_web_services_for_goobi.txt' | |||
65 | --- doc/implementing_active_mq_web_services_for_goobi.txt 1970-01-01 00:00:00 +0000 | |||
66 | +++ doc/implementing_active_mq_web_services_for_goobi.txt 2012-07-27 10:58:19 +0000 | |||
67 | @@ -0,0 +1,80 @@ | |||
68 | 1 | Implementing Active MQ web services for Goobi | ||
69 | 2 | |||
70 | 3 | Active Message Queue is an open source Java Messaging (JMS) implementation | ||
71 | 4 | provided by the Apache Software Foundation. It is intended to be used to | ||
72 | 5 | to connect software components in a flexible way. The core is the Active MQ | ||
73 | 6 | server which can be pictured like a post office. The mail boxes are named | ||
74 | 7 | “queue” or “topic”. Queues work as expected: A producer sends a message where | ||
75 | 8 | a consumer can pick it up. Topics can be pictured as black boards: The main | ||
76 | 9 | difference is: A message read from a queue is removed from the queue. A message | ||
77 | 10 | read from a topic is still available to others. Consumer clients can actively | ||
78 | 11 | check the server or may register listeners with the server to be notified of | ||
79 | 12 | new messages. | ||
80 | 13 | |||
81 | 14 | This behaviour has already been implemented to Goobi: The org.goobi.mq. | ||
82 | 15 | ActiveMQDirector is a ServletContextListener which is registered in web.xml. | ||
83 | 16 | On application startup, it registers all consumers from its “services” variable | ||
84 | 17 | to the server configured in “activeMQ.hostURL”. | ||
85 | 18 | |||
86 | 19 | The elements of this variable are classes extending the abstract class | ||
87 | 20 | ActiveMQProcessor. This class implements the MessageListener and provides | ||
88 | 21 | facilities to handle exceptions and to store the consumer which is required on | ||
89 | 22 | shutdown to disconnect. | ||
90 | 23 | |||
91 | 24 | To implement another web service processor, you have to implement a class which | ||
92 | 25 | extends ActiveMQProcessor and implements its abstract void process(MapMessage). | ||
93 | 26 | Here is the right place to do whatever your processor is intended to do. There | ||
94 | 27 | is a class MapMessageObjectReader which shall be used to type safe retrieve | ||
95 | 28 | complex objects from MapMessages. You must add your new class to the “services” | ||
96 | 29 | variable of ActiveMQDirector then. | ||
97 | 30 | |||
98 | 31 | The Goobi server administrator shall be in control which processors are being | ||
99 | 32 | started, and which queue names they listen on. Implementation of this | ||
100 | 33 | configurability is designed this way: The implementing class must pass its | ||
101 | 34 | queue name to the constructor of the parent class. This is done by implementing | ||
102 | 35 | the constructor like in the following skeleton. If the queue name is not | ||
103 | 36 | configured, it will return null which will prevent the ActiveMQDirector from | ||
104 | 37 | registering it to the server. Inside the class, the queue name is available in | ||
105 | 38 | the global variable “queueName” which is set by the parent class. The | ||
106 | 39 | implementation may use arbitrary “activeMQ.myService.*” entries in | ||
107 | 40 | GoobiConfig.properties for configuration. | ||
108 | 41 | |||
109 | 42 | ---------------------[ Service processor skeleton sample ]--------------------- | ||
110 | 43 | package org.goobi.mq.processores; | ||
111 | 44 | |||
112 | 45 | import org.goobi.mq.*; | ||
113 | 46 | import de.sub.goobi.config.ConfigMain; | ||
114 | 47 | import de.sub.goobi.helper.enums.ReportLevel; | ||
115 | 48 | |||
116 | 49 | public class MyServiceProcessor extends ActiveMQProcessor { | ||
117 | 50 | |||
118 | 51 | public MyServiceProcessor() { | ||
119 | 52 | super(ConfigMain.getParameter("activeMQ.myService.queue", null)); | ||
120 | 53 | } | ||
121 | 54 | |||
122 | 55 | @Override | ||
123 | 56 | protected void process(MapMessageObjectReader args) throws Exception { | ||
124 | 57 | // TODO Auto-generated method stub | ||
125 | 58 | } | ||
126 | 59 | } | ||
127 | 60 | ------------------------------------------------------------------------------- | ||
128 | 61 | |||
129 | 62 | Responses from processors are designed to be handled as WebServiceResult | ||
130 | 63 | objects. Those objects are MapMessages which send themselves to a topic | ||
131 | 64 | configured in “activeMQ.results.topic”. They consist of the Strings “queue” | ||
132 | 65 | (the name of the queue the job ticket was sent to), “id” (a String “id” in | ||
133 | 66 | the MapMessage which is mandatory), “level” and an optional “message”. When | ||
134 | 67 | designing the MapMessage layout to parameterise your web service processor, | ||
135 | 68 | please keep in mind that a String element “id” is mandatory. | ||
136 | 69 | |||
137 | 70 | If process() terminates without error, it is meant to have done its job | ||
138 | 71 | successfully and a WebServiceResult with level “success” will be sent. If | ||
139 | 72 | process() returns an exception, a WebServiceResult with level “fatal” will be | ||
140 | 73 | sent. The exception will be returned as the “message” String. You may also use | ||
141 | 74 | the WebServiceResult class to send messages with the levels “error”, “warn”, | ||
142 | 75 | “info”, “debug”, “verbose” and “ludicrous” which are meant to be informative | ||
143 | 76 | only: | ||
144 | 77 | new WebServiceResult(queueName, args.getMandatoryString("id"), | ||
145 | 78 | ReportLevel.INFO, "Remote host is down, trying again later.") | ||
146 | 79 | .send(); | ||
147 | 80 | |||
148 | 0 | 81 | ||
149 | === added file 'doc/web_service_to_create_new_processes.txt' | |||
150 | --- doc/web_service_to_create_new_processes.txt 1970-01-01 00:00:00 +0000 | |||
151 | +++ doc/web_service_to_create_new_processes.txt 2012-07-27 10:58:19 +0000 | |||
152 | @@ -0,0 +1,104 @@ | |||
153 | 1 | Web service to create new processes | ||
154 | 2 | |||
155 | 3 | Goobi.Production is equiped with a web service interface to automatically | ||
156 | 4 | create new processes based on a given template. This allows the digitization | ||
157 | 5 | process to be initiated from outside the application, for example by assigning | ||
158 | 6 | a new digital ID to a record in a library catalogue (or—at choice of the | ||
159 | 7 | library—by duplicating a record and assigning a new digital ID to the | ||
160 | 8 | duplicate) and then running a script. | ||
161 | 9 | |||
162 | 10 | The web service infrastructure is providet by an Active MQ server (see | ||
163 | 11 | http://activemq.apache.org/ for details) which needs to be downloaded and | ||
164 | 12 | started. Without further configuration, it provides everything necessary on | ||
165 | 13 | port 61616 of the machine in question. | ||
166 | 14 | |||
167 | 15 | The “activeMQ.hostURL” must be set in GoobiConfig.properties to point to this | ||
168 | 16 | server. The “activeMQ.createNewProcess.queue” must be set to point to a queue | ||
169 | 17 | of your choice where Goobi.Production shall pick up orders to create new | ||
170 | 18 | processes. | ||
171 | 19 | |||
172 | 20 | Orders must be javax.jms.MapMessage objects with the following key-value-pairs | ||
173 | 21 | provided: | ||
174 | 22 | |||
175 | 23 | String template | ||
176 | 24 | name of the process template to use | ||
177 | 25 | String opac | ||
178 | 26 | Cataloge to use for lookup | ||
179 | 27 | String field | ||
180 | 28 | Field to look into, usually 12 (PPN) | ||
181 | 29 | String value | ||
182 | 30 | Value to look for, id of physical medium | ||
183 | 31 | String id | ||
184 | 32 | Ticket ID (used in log responses) | ||
185 | 33 | List<String> collections | ||
186 | 34 | Collections to be selected | ||
187 | 35 | Map<String, String> userFields (optional) | ||
188 | 36 | May be used to populates AdditionalField entries | ||
189 | 37 | |||
190 | 38 | Here is a sample java client to do the job. It expects to be passed from the | ||
191 | 39 | command line the Active MQ host (e.g. tcp://localhost:61616), the queue name | ||
192 | 40 | and the parameters as listed above. | ||
193 | 41 | |||
194 | 42 | To run this application, the following JARs from the ActiveMQ server’s /lib | ||
195 | 43 | folder are required on the classpath: | ||
196 | 44 | * activemq-core | ||
197 | 45 | * geronimo-j2ee-management_1.1_spec | ||
198 | 46 | * genonimo-jms_1.1_spec | ||
199 | 47 | * log4j | ||
200 | 48 | * slf4j-api | ||
201 | 49 | * slf4j-log4j12 | ||
202 | 50 | |||
203 | 51 | --------------------------------[ Main.java ]---------------------------------- | ||
204 | 52 | import java.util.*; | ||
205 | 53 | import javax.jms.*; | ||
206 | 54 | import org.apache.activemq.ActiveMQConnectionFactory; | ||
207 | 55 | |||
208 | 56 | public class Main { | ||
209 | 57 | public static int main(String[] args) { try { | ||
210 | 58 | |||
211 | 59 | // Check arguments | ||
212 | 60 | if (args.length < 8 || (args.length % 2) != 0) { | ||
213 | 61 | System.out.println("Parameters: Active MQ host, queue name, " | ||
214 | 62 | + "template name, opac name,"); | ||
215 | 63 | System.out.println(" no. of search field, search " | ||
216 | 64 | + "string, digital id, collection name,"); | ||
217 | 65 | System.out.println(" [additional details field, " | ||
218 | 66 | + "value, [add. details field, value, [..."); | ||
219 | 67 | return 1; | ||
220 | 68 | } | ||
221 | 69 | |||
222 | 70 | // Connect to server | ||
223 | 71 | Connection connection = new ActiveMQConnectionFactory(args[0]) | ||
224 | 72 | .createConnection(); | ||
225 | 73 | connection.start(); | ||
226 | 74 | Session session = connection.createSession(false, | ||
227 | 75 | Session.AUTO_ACKNOWLEDGE); | ||
228 | 76 | Destination destination = session.createQueue(args[1]); | ||
229 | 77 | MessageProducer producer = session.createProducer(destination); | ||
230 | 78 | producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); | ||
231 | 79 | |||
232 | 80 | // Create job ticket | ||
233 | 81 | MapMessage message = session.createMapMessage(); | ||
234 | 82 | message.setString("template", args[2]); | ||
235 | 83 | message.setString("opac", args[3]); | ||
236 | 84 | message.setString("field", args[4]); | ||
237 | 85 | message.setString("value", args[5]); | ||
238 | 86 | message.setString("id", args[6]); | ||
239 | 87 | List<String> collections = new ArrayList<String>(); | ||
240 | 88 | collections.add(args[7]); | ||
241 | 89 | message.setObject("collections", collections); | ||
242 | 90 | Map<String, String> userFields = new HashMap<String, String>(); | ||
243 | 91 | for (int i = 8; i < args.length; i += 2) | ||
244 | 92 | userFields.put(args[i], args[i + 1]); | ||
245 | 93 | if (userFields.size() != 0) | ||
246 | 94 | message.setObject("userFields", userFields); | ||
247 | 95 | |||
248 | 96 | // Send job ticket | ||
249 | 97 | producer.send(message); | ||
250 | 98 | |||
251 | 99 | // Shutdown | ||
252 | 100 | session.close(); | ||
253 | 101 | connection.close(); | ||
254 | 102 | } catch (Exception e) { e.printStackTrace(); return 2; } | ||
255 | 103 | return 0; | ||
256 | 104 | } } | ||
257 | 0 | 105 | ||
258 | === added file 'lib/activemq-core-5.5.1.jar' | |||
259 | 1 | Binary files lib/activemq-core-5.5.1.jar 1970-01-01 00:00:00 +0000 and lib/activemq-core-5.5.1.jar 2012-07-27 10:58:19 +0000 differ | 106 | Binary files lib/activemq-core-5.5.1.jar 1970-01-01 00:00:00 +0000 and lib/activemq-core-5.5.1.jar 2012-07-27 10:58:19 +0000 differ |
260 | === added file 'lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar' | |||
261 | 2 | Binary files lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar 1970-01-01 00:00:00 +0000 and lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar 2012-07-27 10:58:19 +0000 differ | 107 | Binary files lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar 1970-01-01 00:00:00 +0000 and lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar 2012-07-27 10:58:19 +0000 differ |
262 | === added file 'lib/geronimo-jms_1.1_spec-1.1.1.jar' | |||
263 | 3 | Binary files lib/geronimo-jms_1.1_spec-1.1.1.jar 1970-01-01 00:00:00 +0000 and lib/geronimo-jms_1.1_spec-1.1.1.jar 2012-07-27 10:58:19 +0000 differ | 108 | Binary files lib/geronimo-jms_1.1_spec-1.1.1.jar 1970-01-01 00:00:00 +0000 and lib/geronimo-jms_1.1_spec-1.1.1.jar 2012-07-27 10:58:19 +0000 differ |
264 | === added file 'lib/json-simple-1.1.1.jar' | |||
265 | 4 | Binary files lib/json-simple-1.1.1.jar 1970-01-01 00:00:00 +0000 and lib/json-simple-1.1.1.jar 2012-07-27 10:58:19 +0000 differ | 109 | Binary files lib/json-simple-1.1.1.jar 1970-01-01 00:00:00 +0000 and lib/json-simple-1.1.1.jar 2012-07-27 10:58:19 +0000 differ |
266 | === modified file 'src-dubious/dubious/sub/goobi/helper/Page.java' | |||
267 | --- src-dubious/dubious/sub/goobi/helper/Page.java 2012-07-03 13:32:53 +0000 | |||
268 | +++ src-dubious/dubious/sub/goobi/helper/Page.java 2012-07-27 10:58:19 +0000 | |||
269 | @@ -47,7 +47,7 @@ | |||
270 | 47 | public Page(Criteria criteria, int page) { | 47 | public Page(Criteria criteria, int page) { |
271 | 48 | this.page = page; | 48 | this.page = page; |
272 | 49 | LoginForm login = (LoginForm) Helper.getManagedBeanValue("#{LoginForm}"); | 49 | LoginForm login = (LoginForm) Helper.getManagedBeanValue("#{LoginForm}"); |
274 | 50 | if (login.getMyBenutzer() == null) | 50 | if (login == null || login.getMyBenutzer() == null) |
275 | 51 | this.pageSize = 10; | 51 | this.pageSize = 10; |
276 | 52 | else | 52 | else |
277 | 53 | this.pageSize = login.getMyBenutzer().getTabellengroesse().intValue(); | 53 | this.pageSize = login.getMyBenutzer().getTabellengroesse().intValue(); |
278 | 54 | 54 | ||
279 | === modified file 'src/de/sub/goobi/config/ConfigMain.java' | |||
280 | --- src/de/sub/goobi/config/ConfigMain.java 2012-05-30 08:24:19 +0000 | |||
281 | +++ src/de/sub/goobi/config/ConfigMain.java 2012-07-27 10:58:19 +0000 | |||
282 | @@ -119,9 +119,9 @@ | |||
283 | 119 | 119 | ||
284 | 120 | 120 | ||
285 | 121 | /** | 121 | /** |
287 | 122 | * Ermitteln eines bestimmten Paramters der Konfiguration | 122 | * Ermitteln eines bestimmten Parameters der Konfiguration |
288 | 123 | * | 123 | * |
290 | 124 | * @return Paramter als String | 124 | * @return Parameter als String |
291 | 125 | */ | 125 | */ |
292 | 126 | public static String getParameter(String inParameter) { | 126 | public static String getParameter(String inParameter) { |
293 | 127 | try { | 127 | try { |
294 | @@ -135,10 +135,10 @@ | |||
295 | 135 | 135 | ||
296 | 136 | //TODO: Remove this methods, they are provided by Commons Configuration | 136 | //TODO: Remove this methods, they are provided by Commons Configuration |
297 | 137 | /** | 137 | /** |
299 | 138 | * Ermitteln eines bestimmten Paramters der Konfiguration mit Angabe eines | 138 | * Ermitteln eines bestimmten Parameters der Konfiguration mit Angabe eines |
300 | 139 | * Default-Wertes | 139 | * Default-Wertes |
301 | 140 | * | 140 | * |
303 | 141 | * @return Paramter als String | 141 | * @return Parameter als String |
304 | 142 | */ | 142 | */ |
305 | 143 | public static String getParameter(String inParameter, String inDefaultIfNull) { | 143 | public static String getParameter(String inParameter, String inDefaultIfNull) { |
306 | 144 | try { | 144 | try { |
307 | @@ -152,18 +152,18 @@ | |||
308 | 152 | 152 | ||
309 | 153 | 153 | ||
310 | 154 | /** | 154 | /** |
312 | 155 | * Ermitteln eines boolean-Paramters der Konfiguration, default if missing: false | 155 | * Ermitteln eines boolean-Parameters der Konfiguration, default if missing: false |
313 | 156 | * | 156 | * |
315 | 157 | * @return Paramter als String | 157 | * @return Parameter als String |
316 | 158 | */ | 158 | */ |
317 | 159 | public static boolean getBooleanParameter(String inParameter) { | 159 | public static boolean getBooleanParameter(String inParameter) { |
318 | 160 | return getBooleanParameter(inParameter, false); | 160 | return getBooleanParameter(inParameter, false); |
319 | 161 | } | 161 | } |
320 | 162 | 162 | ||
321 | 163 | /** | 163 | /** |
323 | 164 | * Ermitteln eines boolean-Paramters der Konfiguration | 164 | * Ermitteln eines boolean-Parameters der Konfiguration |
324 | 165 | * | 165 | * |
326 | 166 | * @return Paramter als String | 166 | * @return Parameter als String |
327 | 167 | */ | 167 | */ |
328 | 168 | public static boolean getBooleanParameter(String inParameter, boolean inDefault) { | 168 | public static boolean getBooleanParameter(String inParameter, boolean inDefault) { |
329 | 169 | return config.getBoolean(inParameter, inDefault); | 169 | return config.getBoolean(inParameter, inDefault); |
330 | @@ -172,17 +172,12 @@ | |||
331 | 172 | 172 | ||
332 | 173 | 173 | ||
333 | 174 | /** | 174 | /** |
335 | 175 | * Ermitteln eines long-Paramters der Konfiguration | 175 | * Ermitteln eines long-Parameters der Konfiguration |
336 | 176 | * | 176 | * |
338 | 177 | * @return Paramter als Long | 177 | * @return Parameter als Long |
339 | 178 | */ | 178 | */ |
347 | 179 | public static long getLongParameter(String inParameter, int inDefault) { | 179 | public static long getLongParameter(String inParameter, long inDefault) { |
348 | 180 | try { | 180 | return config.getLong(inParameter, inDefault); |
342 | 181 | return config.getLong(inParameter, inDefault); | ||
343 | 182 | } catch (RuntimeException e) { | ||
344 | 183 | myLogger.error(e); | ||
345 | 184 | return 0; | ||
346 | 185 | } | ||
349 | 186 | } | 181 | } |
350 | 187 | 182 | ||
351 | 188 | 183 | ||
352 | @@ -190,7 +185,7 @@ | |||
353 | 190 | /** | 185 | /** |
354 | 191 | * Request int-parameter from Configuration | 186 | * Request int-parameter from Configuration |
355 | 192 | * | 187 | * |
357 | 193 | * @return Paramter as Int | 188 | * @return Parameter as Int |
358 | 194 | */ | 189 | */ |
359 | 195 | public static int getIntParameter(String inParameter) { | 190 | public static int getIntParameter(String inParameter) { |
360 | 196 | return getIntParameter(inParameter, 0); | 191 | return getIntParameter(inParameter, 0); |
361 | @@ -199,7 +194,7 @@ | |||
362 | 199 | /** | 194 | /** |
363 | 200 | * Request int-parameter from Configuration with default-value | 195 | * Request int-parameter from Configuration with default-value |
364 | 201 | * | 196 | * |
366 | 202 | * @return Paramter as Int | 197 | * @return Parameter as Int |
367 | 203 | */ | 198 | */ |
368 | 204 | public static int getIntParameter(String inParameter, int inDefault) { | 199 | public static int getIntParameter(String inParameter, int inDefault) { |
369 | 205 | try { | 200 | try { |
370 | 206 | 201 | ||
371 | === added file 'src/de/sub/goobi/config/DigitalCollections.java' | |||
372 | --- src/de/sub/goobi/config/DigitalCollections.java 1970-01-01 00:00:00 +0000 | |||
373 | +++ src/de/sub/goobi/config/DigitalCollections.java 2012-07-27 10:58:19 +0000 | |||
374 | @@ -0,0 +1,77 @@ | |||
375 | 1 | /* | ||
376 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
377 | 3 | * mass digitization. | ||
378 | 4 | * | ||
379 | 5 | * Visit the websites for more information. | ||
380 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
381 | 7 | * - http://www.goobi.org | ||
382 | 8 | * - http://launchpad.net/goobi-production | ||
383 | 9 | * | ||
384 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
385 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
386 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
387 | 13 | * version. | ||
388 | 14 | * | ||
389 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
390 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
391 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
392 | 18 | * should have received a copy of the GNU General Public License along with this | ||
393 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
394 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
395 | 21 | */ | ||
396 | 22 | |||
397 | 23 | package de.sub.goobi.config; | ||
398 | 24 | |||
399 | 25 | import java.io.File; | ||
400 | 26 | import java.io.FileNotFoundException; | ||
401 | 27 | import java.io.IOException; | ||
402 | 28 | import java.util.ArrayList; | ||
403 | 29 | import java.util.Iterator; | ||
404 | 30 | import java.util.List; | ||
405 | 31 | |||
406 | 32 | import org.jdom.Document; | ||
407 | 33 | import org.jdom.Element; | ||
408 | 34 | import org.jdom.JDOMException; | ||
409 | 35 | import org.jdom.input.SAXBuilder; | ||
410 | 36 | |||
411 | 37 | import de.sub.goobi.beans.Prozess; | ||
412 | 38 | |||
413 | 39 | public class DigitalCollections { | ||
414 | 40 | |||
415 | 41 | @SuppressWarnings("unchecked") | ||
416 | 42 | public static List<String> possibleDigitalCollectionsForProcess( | ||
417 | 43 | Prozess process) throws JDOMException, IOException { | ||
418 | 44 | |||
419 | 45 | List<String> result = new ArrayList<String>(); | ||
420 | 46 | String filename = ConfigMain.getParameter("KonfigurationVerzeichnis") + "digitalCollections.xml"; | ||
421 | 47 | if (!(new File(filename).exists())) { | ||
422 | 48 | throw new FileNotFoundException("File not found: " + filename); | ||
423 | 49 | } | ||
424 | 50 | |||
425 | 51 | /* Datei einlesen und Root ermitteln */ | ||
426 | 52 | SAXBuilder builder = new SAXBuilder(); | ||
427 | 53 | Document doc = builder.build(new File(filename)); | ||
428 | 54 | Element root = doc.getRootElement(); | ||
429 | 55 | /* alle Projekte durchlaufen */ | ||
430 | 56 | List<Element> projekte = root.getChildren(); | ||
431 | 57 | for (Iterator<Element> iter = projekte.iterator(); iter.hasNext();) { | ||
432 | 58 | Element projekt = (Element) iter.next(); | ||
433 | 59 | List<Element> projektnamen = projekt.getChildren("name"); | ||
434 | 60 | for (Iterator<Element> iterator = projektnamen.iterator(); iterator.hasNext();) { | ||
435 | 61 | Element projektname = (Element) iterator.next(); | ||
436 | 62 | |||
437 | 63 | /* | ||
438 | 64 | * wenn der Projektname aufgeführt wird, dann alle Digitalen Collectionen in die Liste | ||
439 | 65 | */ | ||
440 | 66 | if (projektname.getText().equalsIgnoreCase(process.getProjekt().getTitel())) { | ||
441 | 67 | List<Element> myCols = projekt.getChildren("DigitalCollection"); | ||
442 | 68 | for (Iterator<Element> it2 = myCols.iterator(); it2.hasNext();) { | ||
443 | 69 | Element col = (Element) it2.next(); | ||
444 | 70 | result.add(col.getText()); | ||
445 | 71 | } | ||
446 | 72 | } | ||
447 | 73 | } | ||
448 | 74 | } | ||
449 | 75 | return result; | ||
450 | 76 | } | ||
451 | 77 | } | ||
452 | 0 | 78 | ||
453 | === modified file 'src/de/sub/goobi/forms/AktuelleSchritteForm.java' | |||
454 | --- src/de/sub/goobi/forms/AktuelleSchritteForm.java 2012-04-24 13:22:01 +0000 | |||
455 | +++ src/de/sub/goobi/forms/AktuelleSchritteForm.java 2012-07-27 10:58:19 +0000 | |||
456 | @@ -109,7 +109,7 @@ | |||
457 | 109 | * --------------------- Vorgangsdatum generell anzeigen? ------------------- | 109 | * --------------------- Vorgangsdatum generell anzeigen? ------------------- |
458 | 110 | */ | 110 | */ |
459 | 111 | LoginForm login = (LoginForm) Helper.getManagedBeanValue("#{LoginForm}"); | 111 | LoginForm login = (LoginForm) Helper.getManagedBeanValue("#{LoginForm}"); |
461 | 112 | if (login.getMyBenutzer() != null) | 112 | if (login != null && login.getMyBenutzer() != null) |
462 | 113 | anzeigeAnpassen.put("processDate", login.getMyBenutzer().isConfVorgangsdatumAnzeigen()); | 113 | anzeigeAnpassen.put("processDate", login.getMyBenutzer().isConfVorgangsdatumAnzeigen()); |
463 | 114 | else | 114 | else |
464 | 115 | anzeigeAnpassen.put("processDate", false); | 115 | anzeigeAnpassen.put("processDate", false); |
465 | 116 | 116 | ||
466 | === modified file 'src/de/sub/goobi/forms/ProzesskopieForm.java' | |||
467 | --- src/de/sub/goobi/forms/ProzesskopieForm.java 2012-05-09 15:19:19 +0000 | |||
468 | +++ src/de/sub/goobi/forms/ProzesskopieForm.java 2012-07-27 10:58:19 +0000 | |||
469 | @@ -23,6 +23,7 @@ | |||
470 | 23 | package de.sub.goobi.forms; | 23 | package de.sub.goobi.forms; |
471 | 24 | 24 | ||
472 | 25 | import java.io.File; | 25 | import java.io.File; |
473 | 26 | import java.io.FileNotFoundException; | ||
474 | 26 | import java.io.IOException; | 27 | import java.io.IOException; |
475 | 27 | import java.sql.SQLException; | 28 | import java.sql.SQLException; |
476 | 28 | import java.util.ArrayList; | 29 | import java.util.ArrayList; |
477 | @@ -84,6 +85,7 @@ | |||
478 | 84 | import de.sub.goobi.config.ConfigOpac; | 85 | import de.sub.goobi.config.ConfigOpac; |
479 | 85 | import de.sub.goobi.config.ConfigOpacDoctype; | 86 | import de.sub.goobi.config.ConfigOpacDoctype; |
480 | 86 | import de.sub.goobi.config.ConfigProjects; | 87 | import de.sub.goobi.config.ConfigProjects; |
481 | 88 | import de.sub.goobi.config.DigitalCollections; | ||
482 | 87 | import de.sub.goobi.helper.BeanHelper; | 89 | import de.sub.goobi.helper.BeanHelper; |
483 | 88 | import de.sub.goobi.helper.Helper; | 90 | import de.sub.goobi.helper.Helper; |
484 | 89 | import de.sub.goobi.helper.Messages; | 91 | import de.sub.goobi.helper.Messages; |
485 | @@ -932,46 +934,22 @@ | |||
486 | 932 | return possibleDigitalCollection; | 934 | return possibleDigitalCollection; |
487 | 933 | } | 935 | } |
488 | 934 | 936 | ||
489 | 935 | @SuppressWarnings("unchecked") | ||
490 | 936 | private void initializePossibleDigitalCollections() { | 937 | private void initializePossibleDigitalCollections() { |
491 | 937 | possibleDigitalCollection = new ArrayList<String>(); | 938 | possibleDigitalCollection = new ArrayList<String>(); |
523 | 938 | String filename = help.getGoobiConfigDirectory() + "digitalCollections.xml"; | 939 | try{ |
524 | 939 | if (!(new File(filename).exists())) { | 940 | possibleDigitalCollection = DigitalCollections.possibleDigitalCollectionsForProcess(prozessKopie); |
525 | 940 | Helper.setFehlerMeldung("File not found: ", filename); | 941 | } catch (FileNotFoundException e1) { |
526 | 941 | return; | 942 | myLogger.error("File not found: ", e1); |
527 | 942 | } | 943 | Helper.setFehlerMeldung("File not found: ", e1); |
497 | 943 | |||
498 | 944 | try { | ||
499 | 945 | /* Datei einlesen und Root ermitteln */ | ||
500 | 946 | SAXBuilder builder = new SAXBuilder(); | ||
501 | 947 | Document doc = builder.build(new File(filename)); | ||
502 | 948 | Element root = doc.getRootElement(); | ||
503 | 949 | /* alle Projekte durchlaufen */ | ||
504 | 950 | List<Element> projekte = root.getChildren(); | ||
505 | 951 | for (Iterator<Element> iter = projekte.iterator(); iter.hasNext();) { | ||
506 | 952 | Element projekt = (Element) iter.next(); | ||
507 | 953 | List<Element> projektnamen = projekt.getChildren("name"); | ||
508 | 954 | for (Iterator<Element> iterator = projektnamen.iterator(); iterator.hasNext();) { | ||
509 | 955 | Element projektname = (Element) iterator.next(); | ||
510 | 956 | |||
511 | 957 | /* | ||
512 | 958 | * wenn der Projektname aufgeführt wird, dann alle Digitalen Collectionen in die Liste | ||
513 | 959 | */ | ||
514 | 960 | if (projektname.getText().equalsIgnoreCase(prozessKopie.getProjekt().getTitel())) { | ||
515 | 961 | List<Element> myCols = projekt.getChildren("DigitalCollection"); | ||
516 | 962 | for (Iterator<Element> it2 = myCols.iterator(); it2.hasNext();) { | ||
517 | 963 | Element col = (Element) it2.next(); | ||
518 | 964 | possibleDigitalCollection.add(col.getText()); | ||
519 | 965 | } | ||
520 | 966 | } | ||
521 | 967 | } | ||
522 | 968 | } | ||
528 | 969 | } catch (JDOMException e1) { | 944 | } catch (JDOMException e1) { |
529 | 970 | myLogger.error("error while parsing digital collections", e1); | 945 | myLogger.error("error while parsing digital collections", e1); |
530 | 971 | Helper.setFehlerMeldung("Error while parsing digital collections", e1); | 946 | Helper.setFehlerMeldung("Error while parsing digital collections", e1); |
531 | 972 | } catch (IOException e1) { | 947 | } catch (IOException e1) { |
532 | 973 | myLogger.error("error while parsing digital collections", e1); | 948 | myLogger.error("error while parsing digital collections", e1); |
533 | 974 | Helper.setFehlerMeldung("Error while parsing digital collections", e1); | 949 | Helper.setFehlerMeldung("Error while parsing digital collections", e1); |
534 | 950 | } finally { | ||
535 | 951 | if(possibleDigitalCollection == null) | ||
536 | 952 | possibleDigitalCollection = new ArrayList<String>(); | ||
537 | 975 | } | 953 | } |
538 | 976 | 954 | ||
539 | 977 | // if only one collection is possible take it directly | 955 | // if only one collection is possible take it directly |
540 | 978 | 956 | ||
541 | === modified file 'src/de/sub/goobi/helper/Helper.java' | |||
542 | --- src/de/sub/goobi/helper/Helper.java 2012-07-03 13:32:53 +0000 | |||
543 | +++ src/de/sub/goobi/helper/Helper.java 2012-07-27 10:58:19 +0000 | |||
544 | @@ -42,13 +42,16 @@ | |||
545 | 42 | import javax.faces.context.FacesContext; | 42 | import javax.faces.context.FacesContext; |
546 | 43 | import javax.servlet.http.HttpServletRequest; | 43 | import javax.servlet.http.HttpServletRequest; |
547 | 44 | 44 | ||
548 | 45 | import org.apache.log4j.Level; | ||
549 | 45 | import org.apache.log4j.Logger; | 46 | import org.apache.log4j.Logger; |
550 | 47 | import org.goobi.mq.WebServiceResult; | ||
551 | 46 | import org.hibernate.Session; | 48 | import org.hibernate.Session; |
552 | 47 | import org.jdom.Element; | 49 | import org.jdom.Element; |
553 | 48 | 50 | ||
554 | 49 | import de.sub.goobi.beans.Benutzer; | 51 | import de.sub.goobi.beans.Benutzer; |
555 | 50 | import de.sub.goobi.config.ConfigMain; | 52 | import de.sub.goobi.config.ConfigMain; |
556 | 51 | import de.sub.goobi.forms.LoginForm; | 53 | import de.sub.goobi.forms.LoginForm; |
557 | 54 | import de.sub.goobi.helper.enums.ReportLevel; | ||
558 | 52 | import de.sub.goobi.persistence.HibernateUtilOld; | 55 | import de.sub.goobi.persistence.HibernateUtilOld; |
559 | 53 | 56 | ||
560 | 54 | //TODO: Check if more method can be made static | 57 | //TODO: Check if more method can be made static |
561 | @@ -59,6 +62,7 @@ | |||
562 | 59 | 62 | ||
563 | 60 | private String myMetadatenVerzeichnis; | 63 | private String myMetadatenVerzeichnis; |
564 | 61 | private String myConfigVerzeichnis; | 64 | private String myConfigVerzeichnis; |
565 | 65 | public static Map<String, String> activeMQReporting = null; | ||
566 | 62 | 66 | ||
567 | 63 | /** | 67 | /** |
568 | 64 | * Ermitteln eines bestimmten Paramters des Requests | 68 | * Ermitteln eines bestimmten Paramters des Requests |
569 | @@ -145,43 +149,59 @@ | |||
570 | 145 | } | 149 | } |
571 | 146 | 150 | ||
572 | 147 | /** | 151 | /** |
574 | 148 | * Dem aktuellen Formular eine Fehlermeldung für ein bestimmtes Control übergeben | 152 | * The method setMeldung() adds an error message for a given control to the |
575 | 153 | * current form. | ||
576 | 154 | * | ||
577 | 155 | * @param control | ||
578 | 156 | * Name of control that caused the error or “null” if the error | ||
579 | 157 | * was not caused by a control | ||
580 | 158 | * @param messageKey | ||
581 | 159 | * The key of the error message. The method will try to resolve | ||
582 | 160 | * the key against its messages file. | ||
583 | 161 | * @param descriptionKey | ||
584 | 162 | * The description key of the error. The method will try to | ||
585 | 163 | * resolve the key against its messages file. | ||
586 | 164 | * @param infoOnly | ||
587 | 165 | * Set to false for error messages. Set to true for info | ||
588 | 166 | * messages. | ||
589 | 149 | */ | 167 | */ |
591 | 150 | private static void setMeldung(String control, String meldung, String beschreibung, boolean nurInfo) { | 168 | private static void setMeldung(String control, String messageKey, |
592 | 169 | String descriptionKey, boolean infoOnly) { | ||
593 | 151 | FacesContext context = FacesContext.getCurrentInstance(); | 170 | FacesContext context = FacesContext.getCurrentInstance(); |
594 | 152 | 171 | ||
627 | 153 | // Never forget: Strings are immutable | 172 | String message; |
628 | 154 | meldung = meldung.replaceAll("<", "<"); | 173 | String description; |
629 | 155 | meldung = meldung.replaceAll(">", ">"); | 174 | try { |
630 | 156 | beschreibung = beschreibung.replaceAll("<", "<"); | 175 | message = Messages.getString(messageKey); |
631 | 157 | beschreibung = beschreibung.replaceAll(">", ">"); | 176 | } catch (RuntimeException e) { |
632 | 158 | /* wenn kein Kontext da ist, dann die Meldungen in Log */ | 177 | message = messageKey; |
633 | 159 | if (context == null) { | 178 | } |
634 | 160 | if (nurInfo) { | 179 | try { |
635 | 161 | myLogger.info(meldung + " " + beschreibung); | 180 | description = Messages.getString(descriptionKey); |
636 | 162 | } else { | 181 | } catch (RuntimeException e) { |
637 | 163 | myLogger.error(meldung + " " + beschreibung); | 182 | description = descriptionKey; |
638 | 164 | } | 183 | } |
639 | 165 | return; | 184 | |
640 | 166 | } | 185 | message = message.replaceAll("<", "<").replaceAll(">", ">"); |
641 | 167 | 186 | description = description.replaceAll("<", "<").replaceAll(">", ">"); | |
642 | 168 | String msg = ""; | 187 | |
643 | 169 | String beschr = ""; | 188 | String compoundMessage = message.replaceFirst(":\\s*$", "") + ": " |
644 | 170 | try { | 189 | + description; |
645 | 171 | msg = Messages.getString(meldung); | 190 | |
646 | 172 | } catch (RuntimeException e) { | 191 | /* If the Active MQ service is at work, report errors there, too. */ |
647 | 173 | msg = meldung; | 192 | if (activeMQReporting != null) { |
648 | 174 | } | 193 | new WebServiceResult(activeMQReporting.get("queueName"), |
649 | 175 | try { | 194 | activeMQReporting.get("id"), infoOnly ? ReportLevel.INFO |
650 | 176 | beschr = Messages.getString(beschreibung); | 195 | : ReportLevel.ERROR, compoundMessage).send(); |
651 | 177 | } catch (RuntimeException e) { | 196 | } |
652 | 178 | beschr = beschreibung; | 197 | |
653 | 179 | } | 198 | if (context != null) { |
654 | 180 | 199 | context.addMessage( | |
655 | 181 | if (nurInfo) { | 200 | control, |
656 | 182 | context.addMessage(control, new FacesMessage(FacesMessage.SEVERITY_INFO, msg, beschr)); | 201 | new FacesMessage(infoOnly ? FacesMessage.SEVERITY_INFO |
657 | 183 | } else { | 202 | : FacesMessage.SEVERITY_ERROR, message, description)); |
658 | 184 | context.addMessage(control, new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, beschr)); | 203 | } else { // wenn kein Kontext da ist, dann die Meldungen in Log |
659 | 204 | myLogger.log(infoOnly ? Level.INFO : Level.ERROR, compoundMessage); | ||
660 | 185 | } | 205 | } |
661 | 186 | } | 206 | } |
662 | 187 | 207 | ||
663 | 188 | 208 | ||
664 | === modified file 'src/de/sub/goobi/helper/UghHelper.java' | |||
665 | --- src/de/sub/goobi/helper/UghHelper.java 2012-02-22 07:43:02 +0000 | |||
666 | +++ src/de/sub/goobi/helper/UghHelper.java 2012-07-27 10:58:19 +0000 | |||
667 | @@ -42,6 +42,7 @@ | |||
668 | 42 | import ugh.exceptions.DocStructHasNoTypeException; | 42 | import ugh.exceptions.DocStructHasNoTypeException; |
669 | 43 | import ugh.exceptions.MetadataTypeNotAllowedException; | 43 | import ugh.exceptions.MetadataTypeNotAllowedException; |
670 | 44 | import de.sub.goobi.beans.Prozess; | 44 | import de.sub.goobi.beans.Prozess; |
671 | 45 | import de.sub.goobi.config.ConfigMain; | ||
672 | 45 | import de.sub.goobi.helper.exceptions.UghHelperException; | 46 | import de.sub.goobi.helper.exceptions.UghHelperException; |
673 | 46 | 47 | ||
674 | 47 | //TODO: Try to move this methods to UGH (ugh.util.UGHUtils would be a better place) | 48 | //TODO: Try to move this methods to UGH (ugh.util.UGHUtils would be a better place) |
675 | @@ -206,8 +207,13 @@ | |||
676 | 206 | public String convertLanguage(String inLanguage) { | 207 | public String convertLanguage(String inLanguage) { |
677 | 207 | /* Pfad zur Datei ermitteln */ | 208 | /* Pfad zur Datei ermitteln */ |
678 | 208 | FacesContext context = FacesContext.getCurrentInstance(); | 209 | FacesContext context = FacesContext.getCurrentInstance(); |
681 | 209 | HttpSession session = (HttpSession) context.getExternalContext().getSession(false); | 210 | String filename; |
682 | 210 | String filename = session.getServletContext().getRealPath("/WEB-INF") + File.separator + "classes" + File.separator + "opaclanguages.txt"; | 211 | if (context != null) { |
683 | 212 | HttpSession session = (HttpSession) context.getExternalContext().getSession(false); | ||
684 | 213 | filename = session.getServletContext().getRealPath("/WEB-INF") + File.separator + "classes" + File.separator + "opaclanguages.txt"; | ||
685 | 214 | } else { | ||
686 | 215 | filename = ConfigMain.getParameter("KonfigurationVerzeichnis") + "opaclanguages.txt"; | ||
687 | 216 | } | ||
688 | 211 | /* Datei zeilenweise durchlaufen und die Sprache vergleichen */ | 217 | /* Datei zeilenweise durchlaufen und die Sprache vergleichen */ |
689 | 212 | try { | 218 | try { |
690 | 213 | FileInputStream fis = new FileInputStream(filename); | 219 | FileInputStream fis = new FileInputStream(filename); |
691 | @@ -233,8 +239,13 @@ | |||
692 | 233 | String temp = inString; | 239 | String temp = inString; |
693 | 234 | /* Pfad zur Datei ermitteln */ | 240 | /* Pfad zur Datei ermitteln */ |
694 | 235 | FacesContext context = FacesContext.getCurrentInstance(); | 241 | FacesContext context = FacesContext.getCurrentInstance(); |
697 | 236 | HttpSession session = (HttpSession) context.getExternalContext().getSession(false); | 242 | String filename; |
698 | 237 | String filename = session.getServletContext().getRealPath("/WEB-INF") + File.separator + "classes" + File.separator + "opacumlaut.txt"; | 243 | if (context != null) { |
699 | 244 | HttpSession session = (HttpSession) context.getExternalContext().getSession(false); | ||
700 | 245 | filename = session.getServletContext().getRealPath("/WEB-INF") + File.separator + "classes" + File.separator + "opacumlaut.txt"; | ||
701 | 246 | } else { | ||
702 | 247 | filename = ConfigMain.getParameter("KonfigurationVerzeichnis") + "opacumlaut.txt"; | ||
703 | 248 | } | ||
704 | 238 | 249 | ||
705 | 239 | /* Datei zeilenweise durchlaufen und die Sprache vergleichen */ | 250 | /* Datei zeilenweise durchlaufen und die Sprache vergleichen */ |
706 | 240 | try { | 251 | try { |
707 | 241 | 252 | ||
708 | === modified file 'src/de/sub/goobi/helper/WebDav.java' | |||
709 | --- src/de/sub/goobi/helper/WebDav.java 2012-07-03 13:49:14 +0000 | |||
710 | +++ src/de/sub/goobi/helper/WebDav.java 2012-07-27 10:58:19 +0000 | |||
711 | @@ -111,7 +111,8 @@ | |||
712 | 111 | 111 | ||
713 | 112 | public void UploadFromHome(Prozess myProzess) { | 112 | public void UploadFromHome(Prozess myProzess) { |
714 | 113 | Benutzer aktuellerBenutzer = (Benutzer) Helper.getManagedBeanValue("#{LoginForm.myBenutzer}"); | 113 | Benutzer aktuellerBenutzer = (Benutzer) Helper.getManagedBeanValue("#{LoginForm.myBenutzer}"); |
716 | 114 | UploadFromHome(aktuellerBenutzer, myProzess); | 114 | if (aktuellerBenutzer != null) |
717 | 115 | UploadFromHome(aktuellerBenutzer, myProzess); | ||
718 | 115 | } | 116 | } |
719 | 116 | 117 | ||
720 | 117 | public void UploadFromHome(Benutzer inBenutzer, Prozess myProzess) { | 118 | public void UploadFromHome(Benutzer inBenutzer, Prozess myProzess) { |
721 | 118 | 119 | ||
722 | === added file 'src/de/sub/goobi/helper/enums/ReportLevel.java' | |||
723 | --- src/de/sub/goobi/helper/enums/ReportLevel.java 1970-01-01 00:00:00 +0000 | |||
724 | +++ src/de/sub/goobi/helper/enums/ReportLevel.java 2012-07-27 10:58:19 +0000 | |||
725 | @@ -0,0 +1,36 @@ | |||
726 | 1 | /* | ||
727 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
728 | 3 | * mass digitization. | ||
729 | 4 | * | ||
730 | 5 | * Visit the websites for more information. | ||
731 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
732 | 7 | * - http://www.goobi.org | ||
733 | 8 | * - http://launchpad.net/goobi-production | ||
734 | 9 | * | ||
735 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
736 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
737 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
738 | 13 | * version. | ||
739 | 14 | * | ||
740 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
741 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
742 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
743 | 18 | * should have received a copy of the GNU General Public License along with this | ||
744 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
745 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
746 | 21 | */ | ||
747 | 22 | |||
748 | 23 | package de.sub.goobi.helper.enums; | ||
749 | 24 | |||
750 | 25 | /** | ||
751 | 26 | * These are the possible states for output to “activeMQ.results.topic”. | ||
752 | 27 | * | ||
753 | 28 | * @author Matthias Ronge <matthias.ronge@zeutschel.de> | ||
754 | 29 | */ | ||
755 | 30 | public enum ReportLevel { | ||
756 | 31 | FATAL, ERROR, WARN, INFO, SUCCESS, DEBUG, VERBOSE, LUDICROUS; | ||
757 | 32 | |||
758 | 33 | public String toLowerCase() { | ||
759 | 34 | return name().toLowerCase(); | ||
760 | 35 | } | ||
761 | 36 | } | ||
762 | 0 | 37 | ||
763 | === added directory 'src/org/goobi/mq' | |||
764 | === added file 'src/org/goobi/mq/ActiveMQDirector.java' | |||
765 | --- src/org/goobi/mq/ActiveMQDirector.java 1970-01-01 00:00:00 +0000 | |||
766 | +++ src/org/goobi/mq/ActiveMQDirector.java 2012-07-27 10:58:19 +0000 | |||
767 | @@ -0,0 +1,231 @@ | |||
768 | 1 | /* | ||
769 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
770 | 3 | * mass digitization. | ||
771 | 4 | * | ||
772 | 5 | * Visit the websites for more information. | ||
773 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
774 | 7 | * - http://www.goobi.org | ||
775 | 8 | * - http://launchpad.net/goobi-production | ||
776 | 9 | * | ||
777 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
778 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
779 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
780 | 13 | * version. | ||
781 | 14 | * | ||
782 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
783 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
784 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
785 | 18 | * should have received a copy of the GNU General Public License along with this | ||
786 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
787 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
788 | 21 | */ | ||
789 | 22 | |||
790 | 23 | package org.goobi.mq; | ||
791 | 24 | |||
792 | 25 | import javax.jms.Connection; | ||
793 | 26 | import javax.jms.DeliveryMode; | ||
794 | 27 | import javax.jms.Destination; | ||
795 | 28 | import javax.jms.ExceptionListener; | ||
796 | 29 | import javax.jms.JMSException; | ||
797 | 30 | import javax.jms.MessageConsumer; | ||
798 | 31 | import javax.jms.MessageProducer; | ||
799 | 32 | import javax.jms.Session; | ||
800 | 33 | import javax.servlet.ServletContextEvent; | ||
801 | 34 | import javax.servlet.ServletContextListener; | ||
802 | 35 | |||
803 | 36 | import org.apache.activemq.ActiveMQConnectionFactory; | ||
804 | 37 | import org.apache.log4j.Logger; | ||
805 | 38 | import org.goobi.mq.processors.CreateNewProcessProcessor; | ||
806 | 39 | import org.goobi.mq.processors.FinaliseStepProcessor; | ||
807 | 40 | |||
808 | 41 | import de.sub.goobi.config.ConfigMain; | ||
809 | 42 | |||
810 | 43 | /** | ||
811 | 44 | * The class ActiveMQDirector is the head of all Active MQ processors. It | ||
812 | 45 | * implements the ServletContextListener interface and is − if configured in | ||
813 | 46 | * web.xml − called automatically upon server starup. Its job is to connect to | ||
814 | 47 | * the Active MQ server and register the listeners configured. | ||
815 | 48 | * | ||
816 | 49 | * The ActiveMQDirector should ALWAYS be declared in web.xml. The Active MQ | ||
817 | 50 | * services are intended to be run in case that “activeMQ.hostURL” is configured | ||
818 | 51 | * in the GoobiConfig.properties file. To disable the service, the entry there | ||
819 | 52 | * should be emptied or commented out. Otherwise, a valid configuration would | ||
820 | 53 | * not start working and an administrator will hardly have a chance to find out | ||
821 | 54 | * why without inspecting the source code. | ||
822 | 55 | * | ||
823 | 56 | * The class ActiveMQDirector also provides a basic ExceptionListener | ||
824 | 57 | * implementation as required for the connection. | ||
825 | 58 | * | ||
826 | 59 | * @author Matthias Ronge <matthias.ronge@zeutschel.de> | ||
827 | 60 | */ | ||
828 | 61 | public class ActiveMQDirector implements ServletContextListener, | ||
829 | 62 | ExceptionListener { | ||
830 | 63 | private static final Logger logger = Logger | ||
831 | 64 | .getLogger(ActiveMQDirector.class); | ||
832 | 65 | |||
833 | 66 | // *** CONFIGURATION *** | ||
834 | 67 | // When implementing new Services, add them to this list: | ||
835 | 68 | |||
836 | 69 | protected static ActiveMQProcessor[] services; | ||
837 | 70 | static{ | ||
838 | 71 | services = new ActiveMQProcessor[] { | ||
839 | 72 | new CreateNewProcessProcessor(), | ||
840 | 73 | new FinaliseStepProcessor() | ||
841 | 74 | }; | ||
842 | 75 | } | ||
843 | 76 | |||
844 | 77 | protected static Connection connection = null; | ||
845 | 78 | protected static Session session = null; | ||
846 | 79 | protected static MessageProducer resultsTopic; | ||
847 | 80 | |||
848 | 81 | /** | ||
849 | 82 | * The method contextInitialized() is called by the web container on startup | ||
850 | 83 | * and is used to start up the active MQ connection. All processors from | ||
851 | 84 | * services[] are registered. | ||
852 | 85 | * | ||
853 | 86 | * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet | ||
854 | 87 | * .ServletContextEvent) | ||
855 | 88 | */ | ||
856 | 89 | @Override | ||
857 | 90 | public void contextInitialized(ServletContextEvent initialisation) { | ||
858 | 91 | String activeMQHost = ConfigMain.getParameter("activeMQ.hostURL", null); | ||
859 | 92 | if (activeMQHost != null) { | ||
860 | 93 | session = connectToServer(activeMQHost); | ||
861 | 94 | if (session != null) { | ||
862 | 95 | registerListeners(services); | ||
863 | 96 | if (ConfigMain.getParameter("activeMQ.results.topic", null) != null) { | ||
864 | 97 | resultsTopic = setUpReportChannel(ConfigMain.getParameter("activeMQ.results.topic")); | ||
865 | 98 | } } } } | ||
866 | 99 | |||
867 | 100 | /** | ||
868 | 101 | * Sets up a connection to an active MQ server. The connection object is | ||
869 | 102 | * global because it is needed later to shut down the connection. | ||
870 | 103 | * | ||
871 | 104 | * @param server | ||
872 | 105 | * should be “tcp://{host}:{port}” or “vm://localhost” in case | ||
873 | 106 | * that the server is run inside the same virtual machine | ||
874 | 107 | * @return the session object or “null” upon error | ||
875 | 108 | */ | ||
876 | 109 | protected Session connectToServer(String server) { | ||
877 | 110 | try { | ||
878 | 111 | connection = new ActiveMQConnectionFactory(server).createConnection(); | ||
879 | 112 | connection.start(); | ||
880 | 113 | connection.setExceptionListener(this); // → ActiveMQDirector.onException() | ||
881 | 114 | return connection.createSession(false, Session.AUTO_ACKNOWLEDGE); | ||
882 | 115 | } catch (Exception e) { | ||
883 | 116 | logger.fatal("Error connecting to ActiveMQ server, giving up.", e); | ||
884 | 117 | } | ||
885 | 118 | return null; | ||
886 | 119 | } | ||
887 | 120 | |||
888 | 121 | /** | ||
889 | 122 | * This method registers the listeners with the active MQ server. | ||
890 | 123 | * | ||
891 | 124 | * If a queue name was configured for a service, a MessageConsumer is set up | ||
892 | 125 | * to listen on that queue and, in case of incoming messages, make the | ||
893 | 126 | * service process the message. The message checker is saved inside the | ||
894 | 127 | * service to be able to shut it down later. | ||
895 | 128 | */ | ||
896 | 129 | protected void registerListeners(ActiveMQProcessor[] processors) { | ||
897 | 130 | for (ActiveMQProcessor processor : processors) { | ||
898 | 131 | if (processor.getQueueName() != null) { | ||
899 | 132 | MessageConsumer messageChecker = null; | ||
900 | 133 | try { | ||
901 | 134 | Destination queue = session.createQueue(processor.getQueueName()); | ||
902 | 135 | messageChecker = session.createConsumer(queue); | ||
903 | 136 | messageChecker.setMessageListener(processor); | ||
904 | 137 | processor.saveChecker(messageChecker); | ||
905 | 138 | } catch (Exception e) { | ||
906 | 139 | logger.fatal("Error setting up monitoring for \"" + processor.getQueueName() + "\": Giving up.", e); | ||
907 | 140 | } } } } | ||
908 | 141 | |||
909 | 142 | /** | ||
910 | 143 | * This sets up a connection to the topic the results shall be written to. | ||
911 | 144 | * The delivery mode is set so “persistent” to allow consumers not online | ||
912 | 145 | * with the server in the moment of message submission to read the messages | ||
913 | 146 | * later. The log messages are set to be kept on the server for 7 days. This | ||
914 | 147 | * value can be overridden from the GoobiConfig.properties parameter | ||
915 | 148 | * “activeMQ.results.timeToLive”. The time to live must be specified in | ||
916 | 149 | * milliseconds; 0 disables the oblivion. (See also: | ||
917 | 150 | * http://docs.oracle.com/javaee/6/api/javax/jms/MessageProducer.html#setTimeToLive%28long%29 ) | ||
918 | 151 | * | ||
919 | 152 | * @param topic | ||
920 | 153 | * name of the active MQ topic | ||
921 | 154 | * @return a MessageProducer object ready for writing or “null” on error | ||
922 | 155 | */ | ||
923 | 156 | protected MessageProducer setUpReportChannel(String topic) { | ||
924 | 157 | MessageProducer result; | ||
925 | 158 | try { | ||
926 | 159 | Destination channel = session.createTopic(topic); | ||
927 | 160 | result = session.createProducer(channel); | ||
928 | 161 | result.setDeliveryMode(DeliveryMode.PERSISTENT); | ||
929 | 162 | result.setTimeToLive(ConfigMain.getLongParameter("activeMQ.results.timeToLive", 604800000)); | ||
930 | 163 | return result; | ||
931 | 164 | } catch (Exception e) { | ||
932 | 165 | logger.fatal("Error setting up report channel \"" + topic + "\": Giving up.", e); | ||
933 | 166 | } | ||
934 | 167 | return null; | ||
935 | 168 | } | ||
936 | 169 | |||
937 | 170 | /** | ||
938 | 171 | * This method is referenced from this.connectToServer() − see there. | ||
939 | 172 | * | ||
940 | 173 | * @see javax.jms.ExceptionListener#onException(javax.jms.JMSException) | ||
941 | 174 | */ | ||
942 | 175 | @Override | ||
943 | 176 | public void onException(JMSException exce) { | ||
944 | 177 | logger.error(exce); | ||
945 | 178 | } | ||
946 | 179 | |||
947 | 180 | /** | ||
948 | 181 | * Any class that wants to create new Active MQ Messages needs read access | ||
949 | 182 | * to the session, since Active MQ messages don’t have a constructor. | ||
950 | 183 | * | ||
951 | 184 | * @return the session object | ||
952 | 185 | */ | ||
953 | 186 | public static Session getSession() { | ||
954 | 187 | return session; | ||
955 | 188 | } | ||
956 | 189 | |||
957 | 190 | /** | ||
958 | 191 | * Instances of WebServiceResult can be sent by calling their send() method. | ||
959 | 192 | * Therefore, they need read access on their topic. | ||
960 | 193 | * | ||
961 | 194 | * @return the resultsTopic object | ||
962 | 195 | */ | ||
963 | 196 | public static MessageProducer getResultsTopic() { | ||
964 | 197 | return resultsTopic; | ||
965 | 198 | } | ||
966 | 199 | |||
967 | 200 | /** | ||
968 | 201 | * The method contextDestroyed is called by the web container on shutdown. | ||
969 | 202 | * It shuts down all listeners, the session and last, the connection. | ||
970 | 203 | * | ||
971 | 204 | * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet. | ||
972 | 205 | * ServletContextEvent) | ||
973 | 206 | */ | ||
974 | 207 | @Override | ||
975 | 208 | public void contextDestroyed(ServletContextEvent destruction) { | ||
976 | 209 | // Shut down all watchers on any queues | ||
977 | 210 | for (ActiveMQProcessor service : services) { | ||
978 | 211 | MessageConsumer watcher = service.getChecker(); | ||
979 | 212 | if (watcher != null) { | ||
980 | 213 | try { | ||
981 | 214 | watcher.close(); | ||
982 | 215 | } catch (JMSException e) { | ||
983 | 216 | logger.error(e); | ||
984 | 217 | } } } | ||
985 | 218 | |||
986 | 219 | // quit session | ||
987 | 220 | try { | ||
988 | 221 | session.close(); | ||
989 | 222 | } catch (JMSException e) { | ||
990 | 223 | logger.error(e); | ||
991 | 224 | } | ||
992 | 225 | |||
993 | 226 | // shut down connection | ||
994 | 227 | try { | ||
995 | 228 | connection.close(); | ||
996 | 229 | } catch (JMSException e) { | ||
997 | 230 | logger.error(e); | ||
998 | 231 | } } } | ||
999 | 0 | 232 | ||
1000 | === added file 'src/org/goobi/mq/ActiveMQProcessor.java' | |||
1001 | --- src/org/goobi/mq/ActiveMQProcessor.java 1970-01-01 00:00:00 +0000 | |||
1002 | +++ src/org/goobi/mq/ActiveMQProcessor.java 2012-07-27 10:58:19 +0000 | |||
1003 | @@ -0,0 +1,161 @@ | |||
1004 | 1 | /* | ||
1005 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
1006 | 3 | * mass digitization. | ||
1007 | 4 | * | ||
1008 | 5 | * Visit the websites for more information. | ||
1009 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
1010 | 7 | * - http://www.goobi.org | ||
1011 | 8 | * - http://launchpad.net/goobi-production | ||
1012 | 9 | * | ||
1013 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
1014 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
1015 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
1016 | 13 | * version. | ||
1017 | 14 | * | ||
1018 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
1019 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
1020 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
1021 | 18 | * should have received a copy of the GNU General Public License along with this | ||
1022 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
1023 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
1024 | 21 | */ | ||
1025 | 22 | |||
1026 | 23 | package org.goobi.mq; | ||
1027 | 24 | |||
1028 | 25 | import java.util.HashMap; | ||
1029 | 26 | import java.util.Map; | ||
1030 | 27 | |||
1031 | 28 | import javax.jms.MapMessage; | ||
1032 | 29 | import javax.jms.Message; | ||
1033 | 30 | import javax.jms.MessageConsumer; | ||
1034 | 31 | import javax.jms.MessageListener; | ||
1035 | 32 | |||
1036 | 33 | import de.sub.goobi.helper.Helper; | ||
1037 | 34 | import de.sub.goobi.helper.enums.ReportLevel; | ||
1038 | 35 | |||
1039 | 36 | /** | ||
1040 | 37 | * The class ActiveMQProcessor offers general services, such as making the | ||
1041 | 38 | * incoming messages available as MapMessages and publishing the results. When I | ||
1042 | 39 | * came clear that this code would be necessary for every processor, I thought | ||
1043 | 40 | * an abstract class would be the right place for it. ActiveMQProcessor also | ||
1044 | 41 | * provides a place to save the checker for the ActiveMQDirector, to be able to | ||
1045 | 42 | * shut it down later. | ||
1046 | 43 | * | ||
1047 | 44 | * @author Matthias Ronge <matthias.ronge@zeutschel.de> | ||
1048 | 45 | */ | ||
1049 | 46 | public abstract class ActiveMQProcessor implements MessageListener { | ||
1050 | 47 | |||
1051 | 48 | protected String queueName; // the queue name will be available here | ||
1052 | 49 | private MessageConsumer checker; | ||
1053 | 50 | |||
1054 | 51 | /** | ||
1055 | 52 | * Implement the method process() to let your service actually do what you | ||
1056 | 53 | * want him to do. | ||
1057 | 54 | * | ||
1058 | 55 | * @param ticket | ||
1059 | 56 | * A MapMessage which can be processor-specific except that it | ||
1060 | 57 | * requires to have a field “id”. | ||
1061 | 58 | */ | ||
1062 | 59 | protected abstract void process(MapMessageObjectReader ticket) throws Exception; | ||
1063 | 60 | |||
1064 | 61 | /** | ||
1065 | 62 | * Instantiating the class ActiveMQProcessor always requires to pass the | ||
1066 | 63 | * name of the queue it should be attached to. That means, your constructor | ||
1067 | 64 | * should look like this: | ||
1068 | 65 | * | ||
1069 | 66 | * <pre> | ||
1070 | 67 | * public MyServiceProcessor(){ | ||
1071 | 68 | * super(ConfigMain.getParameter("activeMQ.myService.queue", null)); | ||
1072 | 69 | * } | ||
1073 | 70 | * </pre> | ||
1074 | 71 | * | ||
1075 | 72 | * If the parameter is not set in GoobiConfig.properties, it will return | ||
1076 | 73 | * “null” and so prevents it from being set up in ActiveMQDirector. | ||
1077 | 74 | * | ||
1078 | 75 | * @param queueName | ||
1079 | 76 | * the queue name, if configured, or “null” to prevent the | ||
1080 | 77 | * processor from being connected. | ||
1081 | 78 | */ | ||
1082 | 79 | public ActiveMQProcessor(String queueName) { | ||
1083 | 80 | this.queueName = queueName; | ||
1084 | 81 | } | ||
1085 | 82 | |||
1086 | 83 | /** | ||
1087 | 84 | * The method onMessage() provides a corset which checks the message being a | ||
1088 | 85 | * MapMessage, performs a type safe type cast, and extracts the job’s ID to | ||
1089 | 86 | * be able to send useful results to the results topic, which it does after | ||
1090 | 87 | * the abstract method process() has finished. | ||
1091 | 88 | * | ||
1092 | 89 | * Since this will be the same for all processors which use MapMessages, I | ||
1093 | 90 | * extracted the portion into the abstract class. | ||
1094 | 91 | * | ||
1095 | 92 | * @see javax.jms.MessageListener#onMessage(javax.jms.Message) | ||
1096 | 93 | */ | ||
1097 | 94 | @Override | ||
1098 | 95 | public void onMessage(Message arg) { | ||
1099 | 96 | MapMessageObjectReader ticket = null; | ||
1100 | 97 | String ticketID = null; | ||
1101 | 98 | |||
1102 | 99 | try { | ||
1103 | 100 | // Basic check ticket | ||
1104 | 101 | if (arg instanceof MapMessage) | ||
1105 | 102 | ticket = new MapMessageObjectReader((MapMessage) arg); | ||
1106 | 103 | else | ||
1107 | 104 | throw new IllegalArgumentException("Incompatible types."); | ||
1108 | 105 | ticketID = ticket.getMandatoryString("id"); | ||
1109 | 106 | |||
1110 | 107 | // turn on logging | ||
1111 | 108 | Map<String,String> loggingConfig = new HashMap<String,String>(); | ||
1112 | 109 | loggingConfig.put("queueName", queueName); | ||
1113 | 110 | loggingConfig.put("id", ticketID); | ||
1114 | 111 | Helper.activeMQReporting = loggingConfig; | ||
1115 | 112 | |||
1116 | 113 | // process ticket | ||
1117 | 114 | process(ticket); | ||
1118 | 115 | |||
1119 | 116 | // turn off logging again | ||
1120 | 117 | Helper.activeMQReporting = null; | ||
1121 | 118 | |||
1122 | 119 | // if everything ‘s fine, report success | ||
1123 | 120 | new WebServiceResult(queueName, ticketID, ReportLevel.SUCCESS) | ||
1124 | 121 | .send(); | ||
1125 | 122 | |||
1126 | 123 | } catch (Exception exce) { | ||
1127 | 124 | // report any errors | ||
1128 | 125 | new WebServiceResult(queueName, ticketID, ReportLevel.FATAL, | ||
1129 | 126 | exce.getMessage()).send(); | ||
1130 | 127 | } | ||
1131 | 128 | } | ||
1132 | 129 | |||
1133 | 130 | /** | ||
1134 | 131 | * This method is used to get the queue name upon initialisation. | ||
1135 | 132 | * | ||
1136 | 133 | * @return the queue name | ||
1137 | 134 | */ | ||
1138 | 135 | public String getQueueName() { | ||
1139 | 136 | return queueName; | ||
1140 | 137 | } | ||
1141 | 138 | |||
1142 | 139 | /** | ||
1143 | 140 | * The parent object which is there to check for new messages and to trigger | ||
1144 | 141 | * the method onMessage() is saved inside the class, to have it lately for | ||
1145 | 142 | * shutting down the service again. | ||
1146 | 143 | * | ||
1147 | 144 | * @param checker | ||
1148 | 145 | * the MessageConsumer object responsible for checking messages | ||
1149 | 146 | */ | ||
1150 | 147 | |||
1151 | 148 | public void saveChecker(MessageConsumer checker) { | ||
1152 | 149 | this.checker = checker; | ||
1153 | 150 | } | ||
1154 | 151 | |||
1155 | 152 | /** | ||
1156 | 153 | * This method is used to get back the message checking object upon | ||
1157 | 154 | * shutdown. | ||
1158 | 155 | * | ||
1159 | 156 | * @return the MessageConsumer object responsible for checking messages | ||
1160 | 157 | */ | ||
1161 | 158 | public MessageConsumer getChecker() { | ||
1162 | 159 | return checker; | ||
1163 | 160 | } | ||
1164 | 161 | } | ||
1165 | 0 | 162 | ||
1166 | === added file 'src/org/goobi/mq/MapMessageObjectReader.java' | |||
1167 | --- src/org/goobi/mq/MapMessageObjectReader.java 1970-01-01 00:00:00 +0000 | |||
1168 | +++ src/org/goobi/mq/MapMessageObjectReader.java 2012-07-27 10:58:19 +0000 | |||
1169 | @@ -0,0 +1,242 @@ | |||
1170 | 1 | /* | ||
1171 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
1172 | 3 | * mass digitization. | ||
1173 | 4 | * | ||
1174 | 5 | * Visit the websites for more information. | ||
1175 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
1176 | 7 | * - http://www.goobi.org | ||
1177 | 8 | * - http://launchpad.net/goobi-production | ||
1178 | 9 | * | ||
1179 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
1180 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
1181 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
1182 | 13 | * version. | ||
1183 | 14 | * | ||
1184 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
1185 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
1186 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
1187 | 18 | * should have received a copy of the GNU General Public License along with this | ||
1188 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
1189 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
1190 | 21 | */ | ||
1191 | 22 | |||
1192 | 23 | package org.goobi.mq; | ||
1193 | 24 | |||
1194 | 25 | import java.util.Collection; | ||
1195 | 26 | import java.util.HashMap; | ||
1196 | 27 | import java.util.HashSet; | ||
1197 | 28 | import java.util.Map; | ||
1198 | 29 | import java.util.Set; | ||
1199 | 30 | |||
1200 | 31 | import javax.jms.JMSException; | ||
1201 | 32 | import javax.jms.MapMessage; | ||
1202 | 33 | |||
1203 | 34 | public class MapMessageObjectReader { | ||
1204 | 35 | |||
1205 | 36 | private MapMessage ticket; | ||
1206 | 37 | |||
1207 | 38 | /** | ||
1208 | 39 | * This instantiates a new MapMessageObjectReader which is attached to a | ||
1209 | 40 | * given MapMessage. | ||
1210 | 41 | * | ||
1211 | 42 | * @param message | ||
1212 | 43 | */ | ||
1213 | 44 | public MapMessageObjectReader(MapMessage message) { | ||
1214 | 45 | if (message == null) | ||
1215 | 46 | throw new IllegalArgumentException( | ||
1216 | 47 | "MapMessageObjectReader: null argument in constructor."); | ||
1217 | 48 | this.ticket = message; | ||
1218 | 49 | } | ||
1219 | 50 | |||
1220 | 51 | /** | ||
1221 | 52 | * The function getMandatorySetOfString() fetches a Set<String> from a MapMessage. | ||
1222 | 53 | * This is a strict implementation that requires the collection not to be | ||
1223 | 54 | * empty and not to contain the null element. | ||
1224 | 55 | * | ||
1225 | 56 | * Please note that the Set is allowed to contain the empty String (“”). | ||
1226 | 57 | * | ||
1227 | 58 | * @param key | ||
1228 | 59 | * the name of the set to return | ||
1229 | 60 | * @return the set requested | ||
1230 | 61 | * @throws IllegalArgumentException | ||
1231 | 62 | * in case that getObject returns null, the returned object is | ||
1232 | 63 | * not of type Collection, any of the content elements are not | ||
1233 | 64 | * of type String or the collection is empty at all. | ||
1234 | 65 | * @throws JMSException | ||
1235 | 66 | * can be thrown by MapMessage.getObject(String) | ||
1236 | 67 | */ | ||
1237 | 68 | public Set<String> getMandatorySetOfString(String key) | ||
1238 | 69 | throws IllegalArgumentException, JMSException { | ||
1239 | 70 | Set<String> result = new HashSet<String>(); | ||
1240 | 71 | Boolean emptiness = Boolean.TRUE; | ||
1241 | 72 | |||
1242 | 73 | Object collectionObject = ticket.getObject(key); | ||
1243 | 74 | if (collectionObject == null) | ||
1244 | 75 | throw new IllegalArgumentException("Missing mandatory argument: \"" | ||
1245 | 76 | + key + "\""); | ||
1246 | 77 | if (!(collectionObject instanceof Collection<?>)) | ||
1247 | 78 | throw new IllegalArgumentException("Incompatible types: \"" + key | ||
1248 | 79 | + "\" was not found to be of type Collection<?>."); | ||
1249 | 80 | for (Object contentObject : (Collection<?>) collectionObject) { | ||
1250 | 81 | if (contentObject == null || !(contentObject instanceof String)) | ||
1251 | 82 | throw new IllegalArgumentException( | ||
1252 | 83 | "Incompatible types: An element of \"" + key | ||
1253 | 84 | + "\" was not found to be of type String."); | ||
1254 | 85 | result.add((String) contentObject); | ||
1255 | 86 | emptiness = false; | ||
1256 | 87 | } | ||
1257 | 88 | if (emptiness) | ||
1258 | 89 | throw new IllegalArgumentException("Missing mandatory argument: \"" | ||
1259 | 90 | + key + "\" must not be empty."); | ||
1260 | 91 | return result; | ||
1261 | 92 | } | ||
1262 | 93 | |||
1263 | 94 | /** | ||
1264 | 95 | * The function getMandatoryString() fetches a String from a MapMessage. This is | ||
1265 | 96 | * a strict implementation that requires the string not to be null and not | ||
1266 | 97 | * to be empty. | ||
1267 | 98 | * | ||
1268 | 99 | * @param key | ||
1269 | 100 | * the name of the string to return | ||
1270 | 101 | * @return the string requested | ||
1271 | 102 | * @throws IllegalArgumentException | ||
1272 | 103 | * in case that getObject returns null or the returned string is | ||
1273 | 104 | * of length “0”. | ||
1274 | 105 | * @throws JMSException | ||
1275 | 106 | * can be thrown by MapMessage.getString(String) | ||
1276 | 107 | */ | ||
1277 | 108 | public String getMandatoryString(String key) throws IllegalArgumentException, | ||
1278 | 109 | JMSException { | ||
1279 | 110 | String result = ticket.getString(key); | ||
1280 | 111 | if (result == null || result.length() == 0) | ||
1281 | 112 | throw new IllegalArgumentException("Missing mandatory argument: \"" | ||
1282 | 113 | + key + "\""); | ||
1283 | 114 | return result; | ||
1284 | 115 | } | ||
1285 | 116 | |||
1286 | 117 | /** | ||
1287 | 118 | * The function getString() fetches a String from a MapMessage. This is an | ||
1288 | 119 | * access forward to the native function of the MapMessage. You may | ||
1289 | 120 | * consider to use getMandatoryString() instead. | ||
1290 | 121 | * | ||
1291 | 122 | * @param key | ||
1292 | 123 | * the name of the string to return | ||
1293 | 124 | * @return the string requested (may be null or empty) | ||
1294 | 125 | * @throws JMSException | ||
1295 | 126 | * can be thrown by MapMessage.getString(String) | ||
1296 | 127 | */ | ||
1297 | 128 | |||
1298 | 129 | public String getString(String key) throws JMSException { | ||
1299 | 130 | return ticket.getString(key); | ||
1300 | 131 | } | ||
1301 | 132 | |||
1302 | 133 | /** | ||
1303 | 134 | * The function getMandatoryInteger() fetches an Integer object from a MapMessage. This is | ||
1304 | 135 | * a strict implementation that requires the Integer not to be null. | ||
1305 | 136 | * | ||
1306 | 137 | * @param key | ||
1307 | 138 | * the name of the string to return | ||
1308 | 139 | * @return the string requested | ||
1309 | 140 | * @throws IllegalArgumentException | ||
1310 | 141 | * in case that getObject returns null | ||
1311 | 142 | * @throws JMSException | ||
1312 | 143 | * can be thrown by MapMessage.getString(String) | ||
1313 | 144 | */ | ||
1314 | 145 | public Integer getMandatoryInteger(String key) throws IllegalArgumentException, | ||
1315 | 146 | JMSException { | ||
1316 | 147 | Integer result = ticket.getInt(key); | ||
1317 | 148 | if (result == null) | ||
1318 | 149 | throw new IllegalArgumentException("Missing mandatory argument: \"" | ||
1319 | 150 | + key + "\""); | ||
1320 | 151 | return result; | ||
1321 | 152 | } | ||
1322 | 153 | |||
1323 | 154 | /** | ||
1324 | 155 | * The function getMapOfStringToString() fetches a Map<String,String> from a | ||
1325 | 156 | * MapMessage. This is a partly strict implementation that allows no null | ||
1326 | 157 | * element neither as key, nor as value. However, if no object was found for | ||
1327 | 158 | * the given key, or the key returned a null object, the function returns | ||
1328 | 159 | * null. Also, the Map is allowed to contain the empty String (“”) as key | ||
1329 | 160 | * and as values. | ||
1330 | 161 | * | ||
1331 | 162 | * @param key | ||
1332 | 163 | * the name of the map to return | ||
1333 | 164 | * @return the map requested | ||
1334 | 165 | * @throws IllegalArgumentException | ||
1335 | 166 | * in case that the object returned by getObject returned object | ||
1336 | 167 | * is not of type Map or any of the content elements are not of | ||
1337 | 168 | * type String. | ||
1338 | 169 | */ | ||
1339 | 170 | public Map<String, String> getMapOfStringToString(String key) { | ||
1340 | 171 | Map<String, String> result = new HashMap<String, String>(); | ||
1341 | 172 | |||
1342 | 173 | Object mapObject = null; | ||
1343 | 174 | try { | ||
1344 | 175 | mapObject = ticket.getObject(key); | ||
1345 | 176 | } catch (Exception irrelevant) { | ||
1346 | 177 | } | ||
1347 | 178 | if (mapObject == null) | ||
1348 | 179 | return null; | ||
1349 | 180 | |||
1350 | 181 | if (!(mapObject instanceof Map<?, ?>)) | ||
1351 | 182 | throw new IllegalArgumentException("Incompatible types: \"" + key | ||
1352 | 183 | + "\" was not found to be of type Map<?, ?>."); | ||
1353 | 184 | for (Object keyObject : ((Map<?, ?>) mapObject).keySet()) { | ||
1354 | 185 | Object valueObject = ((Map<?, ?>) mapObject).get(keyObject); | ||
1355 | 186 | if (keyObject == null || !(keyObject instanceof String)) | ||
1356 | 187 | throw new IllegalArgumentException( | ||
1357 | 188 | "Incompatible types: A key element of \"" + key | ||
1358 | 189 | + "\" was not found to be of type String."); | ||
1359 | 190 | if (valueObject == null || !(valueObject instanceof String)) | ||
1360 | 191 | throw new IllegalArgumentException( | ||
1361 | 192 | "Incompatible types: A value element of \"" + key | ||
1362 | 193 | + "\" was not found to be of type String."); | ||
1363 | 194 | result.put((String) keyObject, (String) valueObject); | ||
1364 | 195 | } | ||
1365 | 196 | |||
1366 | 197 | return result; | ||
1367 | 198 | } | ||
1368 | 199 | |||
1369 | 200 | /** | ||
1370 | 201 | * The function hasField() tests whether a field can be obtained from a | ||
1371 | 202 | * MapMessage. | ||
1372 | 203 | * | ||
1373 | 204 | * @param string | ||
1374 | 205 | * name of the field | ||
1375 | 206 | * @return true or false | ||
1376 | 207 | * @throws IllegalArgumentException | ||
1377 | 208 | * can be thrown by MapMessage | ||
1378 | 209 | * @throws JMSException | ||
1379 | 210 | * can be thrown by MapMessage | ||
1380 | 211 | */ | ||
1381 | 212 | public boolean hasField(String string) throws IllegalArgumentException, | ||
1382 | 213 | JMSException { | ||
1383 | 214 | String result = ticket.getString(string); | ||
1384 | 215 | return (result != null && result.length() > 0); | ||
1385 | 216 | } | ||
1386 | 217 | } | ||
1387 | 218 | |||
1388 | 219 | |||
1389 | 220 | |||
1390 | 221 | |||
1391 | 222 | |||
1392 | 223 | |||
1393 | 224 | |||
1394 | 225 | |||
1395 | 226 | |||
1396 | 227 | |||
1397 | 228 | |||
1398 | 229 | |||
1399 | 230 | |||
1400 | 231 | |||
1401 | 232 | |||
1402 | 233 | |||
1403 | 234 | |||
1404 | 235 | |||
1405 | 236 | |||
1406 | 237 | |||
1407 | 238 | |||
1408 | 239 | |||
1409 | 240 | |||
1410 | 241 | |||
1411 | 242 | |||
1412 | 0 | 243 | ||
1413 | === added file 'src/org/goobi/mq/WebServiceResult.java' | |||
1414 | --- src/org/goobi/mq/WebServiceResult.java 1970-01-01 00:00:00 +0000 | |||
1415 | +++ src/org/goobi/mq/WebServiceResult.java 2012-07-27 10:58:19 +0000 | |||
1416 | @@ -0,0 +1,88 @@ | |||
1417 | 1 | /* | ||
1418 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
1419 | 3 | * mass digitization. | ||
1420 | 4 | * | ||
1421 | 5 | * Visit the websites for more information. | ||
1422 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
1423 | 7 | * - http://www.goobi.org | ||
1424 | 8 | * - http://launchpad.net/goobi-production | ||
1425 | 9 | * | ||
1426 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
1427 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
1428 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
1429 | 13 | * version. | ||
1430 | 14 | * | ||
1431 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
1432 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
1433 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
1434 | 18 | * should have received a copy of the GNU General Public License along with this | ||
1435 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
1436 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
1437 | 21 | */ | ||
1438 | 22 | |||
1439 | 23 | package org.goobi.mq; | ||
1440 | 24 | |||
1441 | 25 | import javax.jms.MapMessage; | ||
1442 | 26 | |||
1443 | 27 | import org.apache.log4j.Level; | ||
1444 | 28 | import org.apache.log4j.Logger; | ||
1445 | 29 | import org.joda.time.DateTime; | ||
1446 | 30 | import org.joda.time.format.DateTimeFormatter; | ||
1447 | 31 | import org.joda.time.format.ISODateTimeFormat; | ||
1448 | 32 | |||
1449 | 33 | import de.sub.goobi.helper.enums.ReportLevel; | ||
1450 | 34 | |||
1451 | 35 | public class WebServiceResult { | ||
1452 | 36 | private static final Logger logger = Logger.getLogger(ActiveMQDirector.class); | ||
1453 | 37 | |||
1454 | 38 | private String queueName; | ||
1455 | 39 | private String id; | ||
1456 | 40 | private ReportLevel level; | ||
1457 | 41 | private String message = null; | ||
1458 | 42 | |||
1459 | 43 | public WebServiceResult(String queueName, String id, ReportLevel level, | ||
1460 | 44 | String message){ | ||
1461 | 45 | this.queueName = queueName; | ||
1462 | 46 | this.id = id; | ||
1463 | 47 | this.level = level; | ||
1464 | 48 | this.message = message; | ||
1465 | 49 | } | ||
1466 | 50 | |||
1467 | 51 | public WebServiceResult(String queueName, String id, ReportLevel level){ | ||
1468 | 52 | this.queueName = queueName; | ||
1469 | 53 | this.id = id; | ||
1470 | 54 | this.level = level; | ||
1471 | 55 | } | ||
1472 | 56 | |||
1473 | 57 | public void send() { | ||
1474 | 58 | if (ActiveMQDirector.getResultsTopic() == null) { | ||
1475 | 59 | |||
1476 | 60 | // If reporting to ActiveMQ is disabled, write log message | ||
1477 | 61 | logger.log(level == ReportLevel.SUCCESS ? Level.INFO : Level.WARN, | ||
1478 | 62 | "Processing message \"" + id + '@' + queueName | ||
1479 | 63 | + "\" reports " + level.toLowerCase() + "." | ||
1480 | 64 | + (message != null ? " (" + message + ")" : "")); | ||
1481 | 65 | } else { | ||
1482 | 66 | try { | ||
1483 | 67 | MapMessage report = ActiveMQDirector.getSession().createMapMessage(); | ||
1484 | 68 | |||
1485 | 69 | DateTime now = new DateTime(); | ||
1486 | 70 | DateTimeFormatter iso8601formatter = ISODateTimeFormat.dateTime(); | ||
1487 | 71 | report.setString("timestamp", iso8601formatter.print(now)); | ||
1488 | 72 | report.setString("queue", queueName); | ||
1489 | 73 | report.setString("id", id); | ||
1490 | 74 | report.setString("level", level.toLowerCase()); | ||
1491 | 75 | if (message != null) | ||
1492 | 76 | report.setString("message", message); | ||
1493 | 77 | |||
1494 | 78 | ActiveMQDirector.getResultsTopic().send(report); | ||
1495 | 79 | |||
1496 | 80 | } catch (Exception exce) { | ||
1497 | 81 | logger.fatal("Error sending report for \"" + id + '@' | ||
1498 | 82 | + queueName + "\" (" + level.toLowerCase() | ||
1499 | 83 | + (message != null ? ": " + message : "") | ||
1500 | 84 | + "): Giving up.", exce); | ||
1501 | 85 | } | ||
1502 | 86 | } | ||
1503 | 87 | } | ||
1504 | 88 | } | ||
1505 | 0 | 89 | ||
1506 | === added directory 'src/org/goobi/mq/processors' | |||
1507 | === added file 'src/org/goobi/mq/processors/CreateNewProcessProcessor.java' | |||
1508 | --- src/org/goobi/mq/processors/CreateNewProcessProcessor.java 1970-01-01 00:00:00 +0000 | |||
1509 | +++ src/org/goobi/mq/processors/CreateNewProcessProcessor.java 2012-07-27 10:58:19 +0000 | |||
1510 | @@ -0,0 +1,375 @@ | |||
1511 | 1 | /* | ||
1512 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
1513 | 3 | * mass digitization. | ||
1514 | 4 | * | ||
1515 | 5 | * Visit the websites for more information. | ||
1516 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
1517 | 7 | * - http://www.goobi.org | ||
1518 | 8 | * - http://launchpad.net/goobi-production | ||
1519 | 9 | * | ||
1520 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
1521 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
1522 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
1523 | 13 | * version. | ||
1524 | 14 | * | ||
1525 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
1526 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
1527 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
1528 | 18 | * should have received a copy of the GNU General Public License along with this | ||
1529 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
1530 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
1531 | 21 | */ | ||
1532 | 22 | |||
1533 | 23 | package org.goobi.mq.processors; | ||
1534 | 24 | |||
1535 | 25 | import java.util.ArrayList; | ||
1536 | 26 | import java.util.HashSet; | ||
1537 | 27 | import java.util.Iterator; | ||
1538 | 28 | import java.util.List; | ||
1539 | 29 | import java.util.Map; | ||
1540 | 30 | import java.util.Set; | ||
1541 | 31 | |||
1542 | 32 | import org.apache.log4j.Logger; | ||
1543 | 33 | import org.goobi.mq.ActiveMQProcessor; | ||
1544 | 34 | import org.goobi.mq.MapMessageObjectReader; | ||
1545 | 35 | import org.hibernate.Criteria; | ||
1546 | 36 | import org.hibernate.Session; | ||
1547 | 37 | |||
1548 | 38 | import de.sub.goobi.beans.Prozess; | ||
1549 | 39 | import de.sub.goobi.config.ConfigMain; | ||
1550 | 40 | import de.sub.goobi.config.ConfigOpacDoctype; | ||
1551 | 41 | import de.sub.goobi.forms.AdditionalField; | ||
1552 | 42 | import de.sub.goobi.forms.ProzesskopieForm; | ||
1553 | 43 | import de.sub.goobi.helper.Helper; | ||
1554 | 44 | |||
1555 | 45 | /** | ||
1556 | 46 | * CreateNewProcessProcessor is an Apache Active MQ consumer which registers to | ||
1557 | 47 | * a queue configured by "activeMQ.createNewProcess.queue" on application | ||
1558 | 48 | * startup. It was designed to create new processes from outside Goobi. There | ||
1559 | 49 | * are two ways providing to create new processes. If the MapMessage on that | ||
1560 | 50 | * queue contains of all the fields listed, the bibliographic data is retrieved | ||
1561 | 51 | * using a catalogue configured within Goobi. If “opac” is missing, it will try | ||
1562 | 52 | * to create a process just upon the data passed in the “userFields” − “field” | ||
1563 | 53 | * and “value” will be ignored in that case, and the “docType” can be set | ||
1564 | 54 | * manually. | ||
1565 | 55 | * | ||
1566 | 56 | * Field summary: | ||
1567 | 57 | * | ||
1568 | 58 | * <dl> | ||
1569 | 59 | * <dt>String template</dt> | ||
1570 | 60 | * <dd>name of the process template to use.</dd> | ||
1571 | 61 | * <dt>String opac</dt> | ||
1572 | 62 | * <dd>Cataloge to use for lookup.</dd> | ||
1573 | 63 | * <dt>String field</dt> | ||
1574 | 64 | * <dd>Field to look into, usually 12 (PPN).</dd> | ||
1575 | 65 | * <dt>String value</dt> | ||
1576 | 66 | * <dd>Value to look for, id of physical medium</dd> | ||
1577 | 67 | * <dt>String docType</dt> | ||
1578 | 68 | * <dd>DocType value to use if no catalogue request is performed.</dd> | ||
1579 | 69 | * <dt>Set<String> collections</dt> | ||
1580 | 70 | * <dd>Collections to be selected.</dd> | ||
1581 | 71 | * <dt>Map<String, String> userFields collections</dt> | ||
1582 | 72 | * <dd>Fields to be populated manually. | ||
1583 | 73 | * </dd> | ||
1584 | 74 | * </dl> | ||
1585 | 75 | * | ||
1586 | 76 | * @author Matthias Ronge <matthias.ronge@zeutschel.de> | ||
1587 | 77 | */ | ||
1588 | 78 | public class CreateNewProcessProcessor extends ActiveMQProcessor { | ||
1589 | 79 | private static final Logger logger = Logger.getLogger(CreateNewProcessProcessor.class); | ||
1590 | 80 | |||
1591 | 81 | public CreateNewProcessProcessor() { | ||
1592 | 82 | super(ConfigMain.getParameter("activeMQ.createNewProcess.queue", null)); | ||
1593 | 83 | } | ||
1594 | 84 | |||
1595 | 85 | @Override | ||
1596 | 86 | protected void process(MapMessageObjectReader args) throws Exception { | ||
1597 | 87 | |||
1598 | 88 | Set<String> collections = args.getMandatorySetOfString("collections"); | ||
1599 | 89 | String id = args.getMandatoryString("id"); | ||
1600 | 90 | String template = args.getMandatoryString("template"); | ||
1601 | 91 | Map<String, String> userFields = args.getMapOfStringToString("userFields"); | ||
1602 | 92 | if (args.hasField("opac")) { | ||
1603 | 93 | String opac = args.getMandatoryString("opac"); | ||
1604 | 94 | String field = args.getMandatoryString("field"); | ||
1605 | 95 | String value = args.getMandatoryString("value"); | ||
1606 | 96 | createNewProcessMain(template, opac, field, value, id, null, collections, userFields); | ||
1607 | 97 | } else { | ||
1608 | 98 | String docType = args.getString("docType"); | ||
1609 | 99 | createNewProcessMain(template, null, null, null, id, docType, collections, userFields); | ||
1610 | 100 | } | ||
1611 | 101 | |||
1612 | 102 | } | ||
1613 | 103 | |||
1614 | 104 | /** | ||
1615 | 105 | * This is the main routine used to create new processes. | ||
1616 | 106 | * | ||
1617 | 107 | * @param template | ||
1618 | 108 | * titel of the process template the new process shall be derived | ||
1619 | 109 | * from | ||
1620 | 110 | * @param opac | ||
1621 | 111 | * name of the connection to a library catalogue to load the | ||
1622 | 112 | * bibliographic data from (may be null) | ||
1623 | 113 | * @param field | ||
1624 | 114 | * number of the catalogue search field (ignored if “opac” is | ||
1625 | 115 | * null) | ||
1626 | 116 | * @param value | ||
1627 | 117 | * search string (ignored if “opac” is null) | ||
1628 | 118 | * @param id | ||
1629 | 119 | * identifier to be used for the digitisation | ||
1630 | 120 | * @param docType | ||
1631 | 121 | * docType to set (may be null) | ||
1632 | 122 | * @param collections | ||
1633 | 123 | * collections to add the digitisation to | ||
1634 | 124 | * @param userFields | ||
1635 | 125 | * Values for additional fields can be set here (may be null) | ||
1636 | 126 | * @throws Exception | ||
1637 | 127 | * in various cases, such as bad parameters or errors in the | ||
1638 | 128 | * underlying layers | ||
1639 | 129 | */ | ||
1640 | 130 | protected void createNewProcessMain(String template, String opac, String field, String value, String id, String docType, | ||
1641 | 131 | Set<String> collections, Map<String, String> userFields) throws Exception { | ||
1642 | 132 | |||
1643 | 133 | try { | ||
1644 | 134 | ProzesskopieForm newProcess = newProcessFromTemplate(template); | ||
1645 | 135 | newProcess.setDigitalCollections(validCollectionsForProcess(collections, newProcess)); | ||
1646 | 136 | if (opac != null) | ||
1647 | 137 | getBibliorgaphicData(newProcess, opac, field, value); | ||
1648 | 138 | if (docType != null && docTypeIsPossible(newProcess, docType)) | ||
1649 | 139 | newProcess.setDocType(docType); | ||
1650 | 140 | if (userFields != null) | ||
1651 | 141 | setUserFields(newProcess, userFields); | ||
1652 | 142 | newProcess.CalcProzesstitel(); | ||
1653 | 143 | String state = newProcess.NeuenProzessAnlegen(); | ||
1654 | 144 | if (!state.equals("ProzessverwaltungKopie3")) | ||
1655 | 145 | throw new RuntimeException(); | ||
1656 | 146 | logger.info("Created new process: " + id); | ||
1657 | 147 | } catch (Exception exited) { | ||
1658 | 148 | logger.error("Failed to create new process: " + id, exited); | ||
1659 | 149 | throw exited; | ||
1660 | 150 | } | ||
1661 | 151 | } | ||
1662 | 152 | |||
1663 | 153 | /** | ||
1664 | 154 | * The function newProcessFromTemplate() derives a ProzesskopieForm object | ||
1665 | 155 | * from a given template. | ||
1666 | 156 | * | ||
1667 | 157 | * @param templateTitle | ||
1668 | 158 | * titel value of the template to look for | ||
1669 | 159 | * @return a ProzesskopieForm object, prepared from a given template | ||
1670 | 160 | * @throws IllegalArgumentException | ||
1671 | 161 | * if no suitable template is found | ||
1672 | 162 | */ | ||
1673 | 163 | protected ProzesskopieForm newProcessFromTemplate(String templateTitle) throws IllegalArgumentException { | ||
1674 | 164 | ProzesskopieForm result = new ProzesskopieForm(); | ||
1675 | 165 | |||
1676 | 166 | List<Prozess> allTemplates = allTemplatesFromDatabase(); | ||
1677 | 167 | Prozess selectedTemplate = selectTemplateByTitle(allTemplates, templateTitle); | ||
1678 | 168 | result.setProzessVorlage(selectedTemplate); | ||
1679 | 169 | result.Prepare(); | ||
1680 | 170 | return result; | ||
1681 | 171 | } | ||
1682 | 172 | |||
1683 | 173 | /** | ||
1684 | 174 | * This method reads all Prozess objects from the hibernate. | ||
1685 | 175 | * | ||
1686 | 176 | * @return a List<Prozess> holding all templates | ||
1687 | 177 | */ | ||
1688 | 178 | protected List<Prozess> allTemplatesFromDatabase() { | ||
1689 | 179 | Session hibernateSession = Helper.getHibernateSession(); | ||
1690 | 180 | Criteria request = hibernateSession.createCriteria(Prozess.class); | ||
1691 | 181 | |||
1692 | 182 | @SuppressWarnings("unchecked") | ||
1693 | 183 | List<Prozess> result = (List<Prozess>) request.list(); | ||
1694 | 184 | |||
1695 | 185 | return result; | ||
1696 | 186 | } | ||
1697 | 187 | |||
1698 | 188 | /** | ||
1699 | 189 | * The function selectTemplateByTitle() iterates over a List of Prozess and | ||
1700 | 190 | * returns the first element whose titel equals the given templateTitle. | ||
1701 | 191 | * | ||
1702 | 192 | * @param allTemplates | ||
1703 | 193 | * a List<Prozess> which shall be examined | ||
1704 | 194 | * @param templateTitle | ||
1705 | 195 | * the title of the template to be picked up | ||
1706 | 196 | * @return the template, if found | ||
1707 | 197 | * @throws IllegalArgumentException | ||
1708 | 198 | * is thrown, if there is no template matching the given | ||
1709 | 199 | * templateTitle | ||
1710 | 200 | */ | ||
1711 | 201 | protected Prozess selectTemplateByTitle(List<Prozess> allTemplates, String templateTitle) throws IllegalArgumentException { | ||
1712 | 202 | |||
1713 | 203 | Prozess result = null; | ||
1714 | 204 | for (Prozess aTemplate : allTemplates) { | ||
1715 | 205 | if (aTemplate.getTitel().equals(templateTitle)) { | ||
1716 | 206 | result = aTemplate; | ||
1717 | 207 | break; | ||
1718 | 208 | } | ||
1719 | 209 | } | ||
1720 | 210 | if (result == null) | ||
1721 | 211 | throw new IllegalArgumentException("Bad argument: No template \"" + templateTitle + "\" available."); | ||
1722 | 212 | return result; | ||
1723 | 213 | } | ||
1724 | 214 | |||
1725 | 215 | /** | ||
1726 | 216 | * The function validCollectionsForProcess() tests whether a given set of | ||
1727 | 217 | * collections can be assigned to new process. If so, the set of collections | ||
1728 | 218 | * is returned as a list ready for assignment. | ||
1729 | 219 | * | ||
1730 | 220 | * @param collections | ||
1731 | 221 | * a set of collection names to be tested | ||
1732 | 222 | * @param process | ||
1733 | 223 | * a ProzesskopieForm object whose prozessVorlage has been set | ||
1734 | 224 | * @return an ArrayList which can be used to set the digitalCollections of a | ||
1735 | 225 | * ProzesskopieForm | ||
1736 | 226 | * @throws IllegalArgumentException | ||
1737 | 227 | * in case that the given collection isn’t a valid subset of the | ||
1738 | 228 | * digitalCollections possible here | ||
1739 | 229 | */ | ||
1740 | 230 | protected List<String> validCollectionsForProcess(Set<String> collections, ProzesskopieForm process) throws IllegalArgumentException { | ||
1741 | 231 | |||
1742 | 232 | HashSet<String> possibleCollections = new HashSet<String>(process.getPossibleDigitalCollections()); | ||
1743 | 233 | if (!possibleCollections.containsAll(collections)) | ||
1744 | 234 | throw new IllegalArgumentException("Bad argument: One or more elements of \"collections\" is not available for template \"" | ||
1745 | 235 | + process.getProzessVorlage().getTitel() + "\"."); | ||
1746 | 236 | return new ArrayList<String>(collections); | ||
1747 | 237 | } | ||
1748 | 238 | |||
1749 | 239 | /** | ||
1750 | 240 | * The function docTypeIsPossible() tests whether a given docType String can | ||
1751 | 241 | * be applied to a given process template. If so, it will return “true”, | ||
1752 | 242 | * otherwise, it will throw an informative IllegalArgumentException. | ||
1753 | 243 | * | ||
1754 | 244 | * @param dialog | ||
1755 | 245 | * the ProzesskopieForm object to test against | ||
1756 | 246 | * @param docType | ||
1757 | 247 | * the desired docType ID string | ||
1758 | 248 | * @return true on success | ||
1759 | 249 | * @throws IllegalArgumentException | ||
1760 | 250 | * if a docType is not applicable to the template or the docType | ||
1761 | 251 | * isn’t valid | ||
1762 | 252 | */ | ||
1763 | 253 | protected boolean docTypeIsPossible(ProzesskopieForm dialog, String docType) throws IllegalArgumentException { | ||
1764 | 254 | Boolean fieldIsUsed = dialog.getStandardFields().get("doctype"); | ||
1765 | 255 | if (fieldIsUsed == null || fieldIsUsed.equals(Boolean.FALSE)) | ||
1766 | 256 | throw new IllegalArgumentException("Bad argument “docType”: Selected template doesn’t provide the standard field “doctype”."); | ||
1767 | 257 | |||
1768 | 258 | boolean valueIsValid = false; | ||
1769 | 259 | Iterator<ConfigOpacDoctype> configOpacDoctypeIterator = dialog.getAllDoctypes().iterator(); | ||
1770 | 260 | do { | ||
1771 | 261 | ConfigOpacDoctype option = configOpacDoctypeIterator.next(); | ||
1772 | 262 | valueIsValid = docType.equals(option.getTitle()); | ||
1773 | 263 | } while (!valueIsValid && configOpacDoctypeIterator.hasNext()); | ||
1774 | 264 | if (valueIsValid) | ||
1775 | 265 | return true; | ||
1776 | 266 | throw new IllegalArgumentException("Bad argument “docType”: Selected template doesn’t provide a docType “{0}”.".replace("{0}", | ||
1777 | 267 | docType)); | ||
1778 | 268 | } | ||
1779 | 269 | |||
1780 | 270 | /** | ||
1781 | 271 | * The method setUserFields() allows to set any AdditionalField to a user | ||
1782 | 272 | * specific value. | ||
1783 | 273 | * | ||
1784 | 274 | * @param form | ||
1785 | 275 | * a ProzesskopieForm object whose AdditionalField objects are | ||
1786 | 276 | * subject to the change | ||
1787 | 277 | * @param userFields | ||
1788 | 278 | * the data to pass to the form | ||
1789 | 279 | * @throws RuntimeException | ||
1790 | 280 | * in case that no field with a matching title was found in the | ||
1791 | 281 | * ProzesskopieForm object | ||
1792 | 282 | */ | ||
1793 | 283 | protected void setUserFields(ProzesskopieForm form, Map<String, String> userFields) throws RuntimeException { | ||
1794 | 284 | |||
1795 | 285 | for (String key : userFields.keySet()) { | ||
1796 | 286 | setAdditionalField(form, key, userFields.get(key)); | ||
1797 | 287 | } | ||
1798 | 288 | |||
1799 | 289 | } | ||
1800 | 290 | |||
1801 | 291 | /** | ||
1802 | 292 | * Sets the bibliographic data for a new process from a library catalogue. | ||
1803 | 293 | * This is equal to manually choosing a catalogue and a search field, | ||
1804 | 294 | * entering the search string and clicking “Apply”. | ||
1805 | 295 | * | ||
1806 | 296 | * Since the underlying OpacAuswerten() method doesn’t raise exceptions, we | ||
1807 | 297 | * count the populated “additional details” fields before and after running | ||
1808 | 298 | * the request and assume the method to have failed if not even one more | ||
1809 | 299 | * field was populated by the method call. | ||
1810 | 300 | * | ||
1811 | 301 | * @param inputForm | ||
1812 | 302 | * the ProzesskopieForm to be set | ||
1813 | 303 | * @param id | ||
1814 | 304 | * the ticket’s id | ||
1815 | 305 | * @param opac | ||
1816 | 306 | * the value for “Search in Opac” | ||
1817 | 307 | * @param field | ||
1818 | 308 | * the number of the search field, e.g. “12” for PPN. | ||
1819 | 309 | * @param value | ||
1820 | 310 | * the search string | ||
1821 | 311 | * @throws RuntimeException | ||
1822 | 312 | * is thrown if the search didn’t bring any results | ||
1823 | 313 | */ | ||
1824 | 314 | protected void getBibliorgaphicData(ProzesskopieForm inputForm, String opac, String field, String value) throws RuntimeException { | ||
1825 | 315 | |||
1826 | 316 | inputForm.setOpacKatalog(opac); | ||
1827 | 317 | inputForm.setOpacSuchfeld(field); | ||
1828 | 318 | inputForm.setOpacSuchbegriff(value); | ||
1829 | 319 | |||
1830 | 320 | int before = countPopulatedAdditionalFields(inputForm); | ||
1831 | 321 | inputForm.OpacAuswerten(); | ||
1832 | 322 | int afterwards = countPopulatedAdditionalFields(inputForm); | ||
1833 | 323 | |||
1834 | 324 | if (!(afterwards > before)) | ||
1835 | 325 | throw new RuntimeException("Searching the OPAC didn’t yield any results."); | ||
1836 | 326 | } | ||
1837 | 327 | |||
1838 | 328 | /** | ||
1839 | 329 | * The function countPopulatedAdditionalFields() returns the number of | ||
1840 | 330 | * AdditionalFields in the given ProzesskopieForm that have meaningful | ||
1841 | 331 | * content. | ||
1842 | 332 | * | ||
1843 | 333 | * @param form | ||
1844 | 334 | * a ProzesskopieForm object to examine | ||
1845 | 335 | * @return the number of AdditionalFields populated | ||
1846 | 336 | */ | ||
1847 | 337 | protected int countPopulatedAdditionalFields(ProzesskopieForm form) { | ||
1848 | 338 | int result = 0; | ||
1849 | 339 | |||
1850 | 340 | for (AdditionalField field : form.getAdditionalFields()) { | ||
1851 | 341 | String value = field.getWert(); | ||
1852 | 342 | if (value != null && value.length() > 0) | ||
1853 | 343 | result++; | ||
1854 | 344 | } | ||
1855 | 345 | |||
1856 | 346 | return result; | ||
1857 | 347 | } | ||
1858 | 348 | |||
1859 | 349 | /** | ||
1860 | 350 | * The method setAdditionalField() sets the value of an AdditionalField held | ||
1861 | 351 | * by a ProzesskopieForm object. | ||
1862 | 352 | * | ||
1863 | 353 | * @param inputForm | ||
1864 | 354 | * a ProzesskopieForm object | ||
1865 | 355 | * @param key | ||
1866 | 356 | * the title of the AdditionalField whose value shall be modified | ||
1867 | 357 | * @param value | ||
1868 | 358 | * the new value for the AdditionalField | ||
1869 | 359 | * @throws RuntimeException | ||
1870 | 360 | * in case that no field with a matching title was found in the | ||
1871 | 361 | * ProzesskopieForm object | ||
1872 | 362 | */ | ||
1873 | 363 | protected void setAdditionalField(ProzesskopieForm inputForm, String key, String value) throws RuntimeException { | ||
1874 | 364 | |||
1875 | 365 | for (AdditionalField field : inputForm.getAdditionalFields()) { | ||
1876 | 366 | if (key.equals(field.getTitel())) { | ||
1877 | 367 | field.setWert(value); | ||
1878 | 368 | return; | ||
1879 | 369 | } | ||
1880 | 370 | } | ||
1881 | 371 | |||
1882 | 372 | throw new RuntimeException("Couldn’t set “" + key + "” to “" + value + "”: No such field in record."); | ||
1883 | 373 | } | ||
1884 | 374 | |||
1885 | 375 | } | ||
1886 | 0 | 376 | ||
1887 | === added file 'src/org/goobi/mq/processors/FinaliseStepProcessor.java' | |||
1888 | --- src/org/goobi/mq/processors/FinaliseStepProcessor.java 1970-01-01 00:00:00 +0000 | |||
1889 | +++ src/org/goobi/mq/processors/FinaliseStepProcessor.java 2012-07-27 10:58:19 +0000 | |||
1890 | @@ -0,0 +1,97 @@ | |||
1891 | 1 | /* | ||
1892 | 2 | * This file is part of the Goobi Application - a Workflow tool for the support of | ||
1893 | 3 | * mass digitization. | ||
1894 | 4 | * | ||
1895 | 5 | * Visit the websites for more information. | ||
1896 | 6 | * - http://gdz.sub.uni-goettingen.de | ||
1897 | 7 | * - http://www.goobi.org | ||
1898 | 8 | * - http://launchpad.net/goobi-production | ||
1899 | 9 | * | ||
1900 | 10 | * This program is free software; you can redistribute it and/or modify it under | ||
1901 | 11 | * the terms of the GNU General Public License as published by the Free Software | ||
1902 | 12 | * Foundation; either version 2 of the License, or (at your option) any later | ||
1903 | 13 | * version. | ||
1904 | 14 | * | ||
1905 | 15 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
1906 | 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
1907 | 17 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. You | ||
1908 | 18 | * should have received a copy of the GNU General Public License along with this | ||
1909 | 19 | * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, | ||
1910 | 20 | * Suite 330, Boston, MA 02111-1307 USA | ||
1911 | 21 | */ | ||
1912 | 22 | |||
1913 | 23 | package org.goobi.mq.processors; | ||
1914 | 24 | |||
1915 | 25 | import org.apache.commons.lang.StringEscapeUtils; | ||
1916 | 26 | import org.goobi.mq.ActiveMQProcessor; | ||
1917 | 27 | import org.goobi.mq.MapMessageObjectReader; | ||
1918 | 28 | |||
1919 | 29 | import de.sub.goobi.config.ConfigMain; | ||
1920 | 30 | import de.sub.goobi.forms.AktuelleSchritteForm; | ||
1921 | 31 | import de.sub.goobi.persistence.SchrittDAO; | ||
1922 | 32 | |||
1923 | 33 | /** | ||
1924 | 34 | * This is a web service interface to close steps. You have to provide the step | ||
1925 | 35 | * id as “id”; you can add a field “message” which will be added to the wiki | ||
1926 | 36 | * field. | ||
1927 | 37 | * | ||
1928 | 38 | * @author Matthias Ronge <matthias.ronge@zeutschel.de> | ||
1929 | 39 | */ | ||
1930 | 40 | public class FinaliseStepProcessor extends ActiveMQProcessor { | ||
1931 | 41 | |||
1932 | 42 | /** | ||
1933 | 43 | * The default constructor looks up the queue name to use in | ||
1934 | 44 | * GoobiConfig.properties. If that is not configured and “null” is passed to | ||
1935 | 45 | * the super constructor, this will prevent | ||
1936 | 46 | * ActiveMQDirector.registerListeners() from starting this service. | ||
1937 | 47 | */ | ||
1938 | 48 | public FinaliseStepProcessor() { | ||
1939 | 49 | super(ConfigMain.getParameter("activeMQ.finaliseStep.queue", null)); | ||
1940 | 50 | } | ||
1941 | 51 | |||
1942 | 52 | /** | ||
1943 | 53 | * This is the main routine processing incoming tickets. It gets an | ||
1944 | 54 | * AktuelleSchritteForm object, sets it to the appropriate step which is | ||
1945 | 55 | * retrieved from the database, appends the message − if any − to the wiki | ||
1946 | 56 | * field, and executes the form’s the step close function. | ||
1947 | 57 | * | ||
1948 | 58 | * @param ticket | ||
1949 | 59 | * the incoming message | ||
1950 | 60 | * | ||
1951 | 61 | * @see org.goobi.mq.ActiveMQProcessor#process(org.goobi.mq.MapMessageObjectReader) | ||
1952 | 62 | */ | ||
1953 | 63 | protected void process(MapMessageObjectReader ticket) throws Exception { | ||
1954 | 64 | AktuelleSchritteForm dialog = new AktuelleSchritteForm(); | ||
1955 | 65 | Integer stepID = ticket.getMandatoryInteger("id"); | ||
1956 | 66 | dialog.setMySchritt(new SchrittDAO().get(stepID)); | ||
1957 | 67 | if (ticket.hasField("message")) | ||
1958 | 68 | addMessageToWikiField(dialog, ticket.getString("message")); | ||
1959 | 69 | dialog.SchrittDurchBenutzerAbschliessen(); | ||
1960 | 70 | } | ||
1961 | 71 | |||
1962 | 72 | /** | ||
1963 | 73 | * The addMessageToWikiField() method is a helper method which composes the | ||
1964 | 74 | * new wiki field using a StringBuilder. The message is encoded using HTML | ||
1965 | 75 | * entities to prevent certain characters from playing merry havoc when the | ||
1966 | 76 | * message box shall be rendered in a browser later. | ||
1967 | 77 | * | ||
1968 | 78 | * @param form | ||
1969 | 79 | * the AktuelleSchritteForm which is the owner of the wiki field | ||
1970 | 80 | * @param message | ||
1971 | 81 | * the message to append | ||
1972 | 82 | */ | ||
1973 | 83 | protected void addMessageToWikiField(AktuelleSchritteForm form, String message) { | ||
1974 | 84 | StringBuilder composer = new StringBuilder(); | ||
1975 | 85 | String wikiField = form.getWikiField(); | ||
1976 | 86 | if (wikiField != null && wikiField.length() > 0) { | ||
1977 | 87 | composer.append(wikiField); | ||
1978 | 88 | composer.append("\r\n"); | ||
1979 | 89 | } | ||
1980 | 90 | composer.append("<p>"); | ||
1981 | 91 | composer.append(StringEscapeUtils.escapeHtml(message)); | ||
1982 | 92 | composer.append("</p>"); | ||
1983 | 93 | form.setWikiField(composer.toString()); | ||
1984 | 94 | return; | ||
1985 | 95 | } | ||
1986 | 96 | |||
1987 | 97 | } | ||
1988 | 0 | 98 | ||
1989 | === modified file 'src/org/goobi/production/flow/statistics/hibernate/FilterHelper.java' | |||
1990 | --- src/org/goobi/production/flow/statistics/hibernate/FilterHelper.java 2012-02-22 07:43:02 +0000 | |||
1991 | +++ src/org/goobi/production/flow/statistics/hibernate/FilterHelper.java 2012-07-27 10:58:19 +0000 | |||
1992 | @@ -94,7 +94,7 @@ | |||
1993 | 94 | /* identify current user */ | 94 | /* identify current user */ |
1994 | 95 | LoginForm login = (LoginForm) Helper | 95 | LoginForm login = (LoginForm) Helper |
1995 | 96 | .getManagedBeanValue("#{LoginForm}"); | 96 | .getManagedBeanValue("#{LoginForm}"); |
1997 | 97 | if (login.getMyBenutzer() == null) | 97 | if (login == null || login.getMyBenutzer() == null) |
1998 | 98 | return; | 98 | return; |
1999 | 99 | /* init id-list, preset with item 0 */ | 99 | /* init id-list, preset with item 0 */ |
2000 | 100 | List<Integer> idList = new ArrayList<Integer>(); | 100 | List<Integer> idList = new ArrayList<Integer>(); |