001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.fao.geonet.services.metadata;
025:
026: import java.io.File;
027: import java.io.FilenameFilter;
028: import java.util.ArrayList;
029: import java.util.Hashtable;
030: import java.util.List;
031: import java.util.UUID;
032: import jeeves.interfaces.Service;
033: import jeeves.resources.dbms.Dbms;
034: import jeeves.server.ServiceConfig;
035: import jeeves.server.context.ServiceContext;
036: import jeeves.utils.Util;
037: import jeeves.utils.Xml;
038: import org.fao.geonet.GeonetContext;
039: import org.fao.geonet.constants.Geonet;
040: import org.fao.geonet.constants.Params;
041: import org.fao.geonet.kernel.DataManager;
042: import org.jdom.Element;
043: import org.jdom.Namespace;
044:
045: // FIXME: this class could be moved to DataManager
046:
047: //=============================================================================
048:
049: /** Import all metadata found inside a given directory
050: */
051:
052: public class ImportFromDir implements Service {
053: private FilenameFilter filter = new FilenameFilter() {
054: public boolean accept(File dir, String name) {
055: if (name.equals(CONFIG_FILE))
056: return false;
057:
058: return !name.startsWith(".");
059: }
060: };
061:
062: //--------------------------------------------------------------------------
063:
064: private FilenameFilter mdFilter = new FilenameFilter() {
065: public boolean accept(File dir, String name) {
066: if (name.equals(CONFIG_FILE))
067: return false;
068:
069: if (name.startsWith("."))
070: return false;
071:
072: return name.endsWith(".xml");
073: }
074: };
075:
076: //--------------------------------------------------------------------------
077:
078: private String stylePath;
079:
080: private static final String CONFIG_FILE = "import-config.xml";
081:
082: //--------------------------------------------------------------------------
083: //---
084: //--- Init
085: //---
086: //--------------------------------------------------------------------------
087:
088: public void init(String appPath, ServiceConfig params)
089: throws Exception {
090: this .stylePath = appPath + Geonet.Path.IMPORT_STYLESHEETS;
091: }
092:
093: //--------------------------------------------------------------------------
094: //---
095: //--- API
096: //---
097: //--------------------------------------------------------------------------
098:
099: public Element exec(Element params, ServiceContext context)
100: throws Exception {
101: String dir = Util.getParam(params, Params.DIR);
102: File file = new File(dir + "/" + CONFIG_FILE);
103:
104: //-----------------------------------------------------------------------
105:
106: long start = System.currentTimeMillis();
107:
108: int result;
109:
110: if (file.exists())
111: result = configImport(params, context, file);
112: else
113: result = standardImport(params, context);
114:
115: long end = System.currentTimeMillis();
116: long duration = (end - start) / 1000;
117:
118: context.info("Import time is :" + duration + " secs");
119:
120: return new Element("ok").setText("records:" + result);
121: }
122:
123: //--------------------------------------------------------------------------
124: //---
125: //--- Standard import
126: //---
127: //--------------------------------------------------------------------------
128:
129: private int standardImport(Element params, ServiceContext context)
130: throws Exception {
131: GeonetContext gc = (GeonetContext) context
132: .getHandlerContext(Geonet.CONTEXT_NAME);
133: DataManager dm = gc.getDataManager();
134:
135: String dir = Util.getParam(params, Params.DIR);
136: String schema = Util.getParam(params, Params.SCHEMA);
137: String group = Util.getParam(params, Params.GROUP);
138: String category = Util.getParam(params, Params.CATEGORY);
139: String style = Util.getParam(params, Params.STYLESHEET);
140:
141: boolean validate = Util
142: .getParam(params, Params.VALIDATE, "off").equals("on");
143:
144: File files[] = new File(dir).listFiles(mdFilter);
145:
146: if (files == null)
147: throw new Exception("Directory not found: " + dir);
148:
149: ArrayList<Element> alMetadata = new ArrayList<Element>();
150:
151: //--- first collect metadata
152:
153: for (int i = 0; i < files.length; i++) {
154: context.debug("Importing : " + files[i]);
155:
156: Element xml = Xml.loadFile(files[i]);
157:
158: if (!style.equals("_none_"))
159: xml = Xml.transform(xml, stylePath + "/" + style);
160:
161: if (validate)
162: dm.validate(schema, xml);
163:
164: alMetadata.add(xml);
165: }
166:
167: //--- then insert them. At this stage they are well formed and we should not
168: //--- get exceptions that invalidate the index
169:
170: for (Element xml : alMetadata)
171: insert(schema, xml, group, context, category);
172:
173: return files.length;
174: }
175:
176: //--------------------------------------------------------------------------
177: //---
178: //--- Config import
179: //---
180: //--------------------------------------------------------------------------
181:
182: private int configImport(Element params, ServiceContext context,
183: File configFile) throws Exception {
184: GeonetContext gc = (GeonetContext) context
185: .getHandlerContext(Geonet.CONTEXT_NAME);
186: DataManager dm = gc.getDataManager();
187:
188: ImportConfig config = new ImportConfig(configFile, context);
189:
190: String dir = Util.getParam(params, Params.DIR);
191: String group = Util.getParam(params, Params.GROUP);
192: String style = Util.getParam(params, Params.STYLESHEET);
193:
194: boolean validate = Util
195: .getParam(params, Params.VALIDATE, "off").equals("on");
196:
197: File sites[] = new File(dir).listFiles(filter);
198:
199: if (sites == null)
200: throw new Exception("Directory not found : " + dir);
201:
202: int counter = 0;
203:
204: ArrayList<ImportInfo> alImport = new ArrayList<ImportInfo>();
205:
206: for (int i = 0; i < sites.length; i++) {
207: context.debug("Scanning site : " + sites[i]);
208:
209: File categs[] = sites[i].listFiles(filter);
210:
211: if (categs == null)
212: throw new Exception("Cannot scan categories in : "
213: + sites[i].getPath());
214:
215: for (int j = 0; j < categs.length; j++) {
216: context.debug(" Scanning category : " + categs[j]);
217:
218: String catDir = categs[j].getName();
219: File files[] = categs[j].listFiles(mdFilter);
220:
221: if (files == null)
222: throw new Exception("Cannot scan files in : "
223: + categs[j].getPath());
224:
225: for (int k = 0; k < files.length; k++) {
226: Element xml = Xml.loadFile(files[k]);
227:
228: if (!style.equals("_none_"))
229: xml = Xml.transform(xml, stylePath + "/"
230: + style);
231:
232: String category = config.mapCategory(catDir);
233: String schema = config.mapSchema(catDir);
234:
235: if (validate)
236: dm.validate(schema, xml);
237:
238: alImport.add(new ImportInfo(schema, category, xml));
239: counter++;
240: }
241: }
242: }
243:
244: //--- step 2 : insert metadata
245:
246: for (ImportInfo ii : alImport)
247: insert(ii.schema, ii.xml, group, context, ii.category);
248:
249: return counter;
250: }
251:
252: //--------------------------------------------------------------------------
253: //---
254: //--- Private methods
255: //---
256: //--------------------------------------------------------------------------
257:
258: private void insert(String schema, Element xml, String group,
259: ServiceContext context, String category) throws Exception {
260: GeonetContext gc = (GeonetContext) context
261: .getHandlerContext(Geonet.CONTEXT_NAME);
262: DataManager dm = gc.getDataManager();
263:
264: //-----------------------------------------------------------------------
265: //--- if the uuid does not exist we generate it
266:
267: String uuid = dm.extractUUID(schema, xml);
268:
269: if (uuid.length() == 0)
270: uuid = UUID.randomUUID().toString();
271:
272: //-----------------------------------------------------------------------
273: //--- insert metadata into the system
274:
275: Dbms dbms = (Dbms) context.getResourceManager().open(
276: Geonet.Res.MAIN_DB);
277:
278: String id = dm.insertMetadata(dbms, schema, group, xml, context
279: .getSerialFactory(), gc.getSiteId(), uuid, context
280: .getUserSession().getUserIdAsInt());
281:
282: if (!"_none_".equals(category))
283: dm.setCategory(dbms, id, category);
284: }
285: }
286:
287: //=============================================================================
288:
289: class ImportInfo {
290: public String schema;
291: public String category;
292: public Element xml;
293:
294: //--------------------------------------------------------------------------
295:
296: public ImportInfo(String schema, String category, Element xml) {
297: this .schema = schema;
298: this .category = category;
299: this .xml = xml;
300: }
301: }
302:
303: //=============================================================================
304:
305: class ImportConfig {
306: private static final String CATEGORY_MAPPING = "categoryMapping";
307: private static final String SCHEMA_MAPPING = "schemaMapping";
308:
309: private static final String MAPPING = "mapping";
310: private static final String DEFAULT = "default";
311:
312: private static final String ATTR_DIR = "dir";
313: private static final String ATTR_TO = "to";
314:
315: //--------------------------------------------------------------------------
316:
317: private Hashtable htCategId = new Hashtable();
318: private Hashtable htCategMapping = new Hashtable();
319: private Hashtable htSchemaMapping = new Hashtable();
320:
321: private String defaultCateg;
322: private String defaultSchema;
323:
324: //--------------------------------------------------------------------------
325: //---
326: //--- Constructor
327: //---
328: //--------------------------------------------------------------------------
329:
330: public ImportConfig(File configFile, ServiceContext context)
331: throws Exception {
332: GeonetContext gc = (GeonetContext) context
333: .getHandlerContext(Geonet.CONTEXT_NAME);
334: DataManager dm = gc.getDataManager();
335:
336: Dbms dbms = (Dbms) context.getResourceManager().open(
337: Geonet.Res.MAIN_DB);
338:
339: Element config = Xml.loadFile(configFile);
340:
341: fillCategIds(dbms);
342:
343: mapCategor(config.getChild(CATEGORY_MAPPING));
344: mapSchemas(config.getChild(SCHEMA_MAPPING), dm);
345: }
346:
347: //--------------------------------------------------------------------------
348: //---
349: //--- API methods
350: //---
351: //--------------------------------------------------------------------------
352:
353: public String mapCategory(String catDir) {
354: String mapping = (String) htCategMapping.get(catDir);
355:
356: if (mapping == null)
357: mapping = defaultCateg;
358:
359: return mapping;
360: }
361:
362: //--------------------------------------------------------------------------
363:
364: public String mapSchema(String catDir) {
365: String mapping = (String) htSchemaMapping.get(catDir);
366:
367: if (mapping == null)
368: mapping = defaultSchema;
369:
370: return mapping;
371: }
372:
373: //--------------------------------------------------------------------------
374: //---
375: //--- Private methods
376: //---
377: //--------------------------------------------------------------------------
378:
379: private void fillCategIds(Dbms dbms) throws Exception {
380: String query = "SELECT * FROM Categories";
381:
382: List idsList = dbms.select(query).getChildren();
383:
384: for (int i = 0; i < idsList.size(); i++) {
385: Element record = (Element) idsList.get(i);
386:
387: String id = record.getChildText("id");
388: String name = record.getChildText("name");
389:
390: htCategId.put(name, id);
391: }
392: }
393:
394: //--------------------------------------------------------------------------
395:
396: private void mapCategor(Element categMapping) {
397: List list = categMapping.getChildren(MAPPING);
398:
399: for (int i = 0; i < list.size(); i++) {
400: Element el = (Element) list.get(i);
401:
402: String dir = el.getAttributeValue(ATTR_DIR);
403: String to = el.getAttributeValue(ATTR_TO);
404:
405: String categId = (String) htCategId.get(to);
406:
407: if (categId == null)
408: throw new IllegalArgumentException(
409: "Category not found : " + to);
410:
411: htCategMapping.put(dir, categId);
412: }
413:
414: String defaultTo = categMapping.getChild(DEFAULT)
415: .getAttributeValue(ATTR_TO);
416: String defaultId = (String) htCategId.get(defaultTo);
417:
418: if (defaultId == null)
419: throw new IllegalArgumentException(
420: "Default category not found : " + defaultTo);
421:
422: defaultCateg = defaultTo;
423: }
424:
425: //--------------------------------------------------------------------------
426:
427: private void mapSchemas(Element schemaMapping, DataManager dm) {
428: List list = schemaMapping.getChildren(MAPPING);
429:
430: for (int i = 0; i < list.size(); i++) {
431: Element el = (Element) list.get(i);
432:
433: String dir = el.getAttributeValue(ATTR_DIR);
434: String to = el.getAttributeValue(ATTR_TO);
435:
436: if (!dm.existsSchema(to))
437: throw new IllegalArgumentException(
438: "Schema not found : " + to);
439:
440: htSchemaMapping.put(dir, to);
441: }
442:
443: String defaultTo = schemaMapping.getChild(DEFAULT)
444: .getAttributeValue(ATTR_TO);
445:
446: if (!dm.existsSchema(defaultTo))
447: throw new IllegalArgumentException(
448: "Default schema not found : " + defaultTo);
449:
450: defaultSchema = defaultTo;
451: }
452: }
453:
454: //=============================================================================
|