1 package org.andromda.repositories.mdr;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.net.URL;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.Map;
11 import javax.jmi.model.ModelPackage;
12 import javax.jmi.model.MofPackage;
13 import javax.jmi.reflect.RefPackage;
14 import javax.jmi.xmi.MalformedXMIException;
15 import javax.jmi.xmi.XmiReader;
16 import org.andromda.core.common.ClassUtils;
17 import org.andromda.core.common.ComponentContainer;
18 import org.andromda.core.common.ExceptionUtils;
19 import org.andromda.core.common.ResourceUtils;
20 import org.andromda.core.metafacade.ModelAccessFacade;
21 import org.andromda.core.repository.RepositoryFacade;
22 import org.andromda.core.repository.RepositoryFacadeException;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.log4j.Logger;
25 import org.netbeans.api.mdr.CreationFailedException;
26 import org.netbeans.api.mdr.MDRManager;
27 import org.netbeans.api.mdr.MDRepository;
28 import org.netbeans.api.xmi.XMIReaderFactory;
29 import org.netbeans.api.xmi.XMIWriter;
30 import org.netbeans.api.xmi.XMIWriterFactory;
31
32
33
34
35
36
37
38
39
40 public class MDRepositoryFacade
41 implements RepositoryFacade
42 {
43 private static final Logger logger = Logger.getLogger(MDRepositoryFacade.class);
44 private ModelAccessFacade modelFacade = null;
45 private MDRepository repository = null;
46
47
48
49 protected URL metamodelUri;
50
51
52
53 protected RefPackage model = null;
54
55
56
57
58 public MDRepositoryFacade()
59 {
60
61 System.setProperty(
62 "org.netbeans.mdr.storagemodel.StorageFactoryClassName",
63 "org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl");
64
65 final MDRManager mdrManager = MDRManager.getDefault();
66 if (mdrManager == null)
67 {
68 throw new RepositoryFacadeException("Could not retrieve the MDR manager");
69 }
70 this.repository = mdrManager.getDefaultRepository();
71 }
72
73
74
75
76 private boolean open = false;
77
78
79
80
81
82
83
84
85 public void open()
86 {
87 if (!this.open)
88 {
89 repository.beginTrans(true);
90 this.open = true;
91 }
92 }
93
94
95
96
97
98
99
100
101 public void close()
102 {
103 if (this.open)
104 {
105 repository.endTrans(false);
106 this.clear();
107 MDRManager.getDefault().shutdownAll();
108 this.open = false;
109 }
110 }
111
112
113
114
115 public void readModel(
116 String[] uris,
117 String[] moduleSearchPath)
118 {
119 try
120 {
121 final MofPackage metaModel = this.loadMetaModel(this.getMetamodelUri());
122 this.model = this.loadModel(
123 uris,
124 moduleSearchPath,
125 metaModel);
126 }
127 catch (final Throwable throwable)
128 {
129 throw new RepositoryFacadeException(throwable);
130 }
131 }
132
133
134
135
136
137
138 private URL getMetamodelUri()
139 {
140 if (this.metamodelUri == null)
141 {
142 throw new RepositoryFacadeException("No metamodel was defined");
143 }
144 return this.metamodelUri;
145 }
146
147
148
149
150 public void readModel(
151 final InputStream[] streams,
152 final String[] uris,
153 final String[] moduleSearchPath)
154 {
155 if (streams != null && uris != null && uris.length != streams.length)
156 {
157 throw new IllegalArgumentException("'streams' and 'uris' must be of the same length");
158 }
159 try
160 {
161 final MofPackage metaModel = this.loadMetaModel(this.getMetamodelUri());
162 this.model = this.loadModel(
163 streams,
164 uris,
165 moduleSearchPath,
166 metaModel);
167 }
168 catch (final Throwable throwable)
169 {
170 throw new RepositoryFacadeException(throwable);
171 }
172 }
173
174
175
176
177 private static final String DEFAULT_XMI_VERSION = "1.2";
178
179
180
181
182 private static final String DEFAULT_ENCODING = "UTF-8";
183
184
185
186
187
188 public void writeModel(
189 Object model,
190 String outputLocation,
191 String xmiVersion)
192 {
193 this.writeModel(
194 model,
195 outputLocation,
196 xmiVersion,
197 null);
198 }
199
200
201
202
203
204
205 public void setMetamodelLocation(final String metamodelLocation)
206 {
207 this.metamodelUri = MDRepositoryFacade.class.getResource(metamodelLocation);
208 if (this.metamodelUri == null)
209 {
210 ResourceUtils.toURL(metamodelLocation);
211 }
212 if (this.metamodelUri == null)
213 {
214 throw new RepositoryFacadeException("No metamodel could be loaded from --> '" + metamodelLocation + '\'');
215 }
216 }
217
218
219
220
221 private String metamodelPackage;
222
223
224
225
226
227
228 public void setMetamodelPackage(final String metamodelPackage)
229 {
230 this.metamodelPackage = metamodelPackage;
231 }
232
233
234
235
236 private String xmiReaderFactory;
237
238
239
240
241
242
243 public void setXmiReaderFactory(final String xmiReaderFactory)
244 {
245 this.xmiReaderFactory = xmiReaderFactory;
246 }
247
248
249
250
251 private Map<String, XMIReaderFactory> xmiReaderFactoryInstances = new HashMap<String, XMIReaderFactory>();
252
253
254
255
256
257
258
259
260 private synchronized XMIReaderFactory getXMIReaderFactory()
261 throws InstantiationException, IllegalAccessException
262 {
263 XMIReaderFactory factory =
264 this.xmiReaderFactoryInstances.get(this.xmiReaderFactory);
265 if (factory == null)
266 {
267 if (StringUtils.isBlank(this.xmiReaderFactory))
268 {
269 throw new RepositoryFacadeException("No 'xmiReaderFactory' has been set");
270 }
271 Object instance = ClassUtils.loadClass(this.xmiReaderFactory).newInstance();
272 if (instance instanceof XMIReaderFactory)
273 {
274 factory = (XMIReaderFactory)instance;
275 this.xmiReaderFactoryInstances.put(
276 this.xmiReaderFactory,
277 factory);
278 }
279 else
280 {
281 throw new RepositoryFacadeException("The 'xmiReaderFactory' must be an instance of '" +
282 XMIReaderFactory.class.getName() + '\'');
283 }
284 }
285 return factory;
286 }
287
288
289
290
291
292
293
294
295
296 public void writeModel(
297 Object model,
298 String outputLocation,
299 String xmiVersion,
300 String encoding)
301 {
302 ExceptionUtils.checkNull(
303 "model",
304 model);
305 ExceptionUtils.checkNull(
306 "outputLocation",
307 outputLocation);
308 ExceptionUtils.checkAssignable(
309 RefPackage.class,
310 "model",
311 model.getClass());
312 if (StringUtils.isEmpty(xmiVersion))
313 {
314 xmiVersion = DEFAULT_XMI_VERSION;
315 }
316 if (StringUtils.isEmpty(encoding))
317 {
318 encoding = DEFAULT_ENCODING;
319 }
320 try
321 {
322
323 final File file = new File(outputLocation);
324 final File parent = file.getParentFile();
325 if (parent != null)
326 {
327 parent.mkdirs();
328 }
329 FileOutputStream outputStream = new FileOutputStream(file);
330 final XMIWriter xmiWriter = XMIWriterFactory.getDefault().createXMIWriter();
331 xmiWriter.getConfiguration().setEncoding(encoding);
332 xmiWriter.write(
333 outputStream,
334 outputLocation,
335 (RefPackage)model,
336 xmiVersion);
337 outputStream.close();
338 outputStream = null;
339 }
340 catch (final Throwable throwable)
341 {
342 throw new RepositoryFacadeException(throwable);
343 }
344 }
345
346 private Class modelAccessFacade;
347
348
349
350
351
352
353 public void setModelAccessFacade(Class modelAccessFacade)
354 {
355 this.modelAccessFacade = modelAccessFacade;
356 }
357
358
359
360
361 public ModelAccessFacade getModel()
362 {
363 if (this.modelFacade == null)
364 {
365 try
366 {
367 this.modelFacade =
368 (ModelAccessFacade)ComponentContainer.instance().newComponent(
369 this.modelAccessFacade,
370 ModelAccessFacade.class);
371 }
372 catch (final Throwable throwable)
373 {
374 throw new RepositoryFacadeException(throwable);
375 }
376 }
377 if (this.model != null)
378 {
379 this.modelFacade.setModel(this.model);
380 }
381 else
382 {
383 this.modelFacade = null;
384 }
385 return this.modelFacade;
386 }
387
388
389
390
391
392
393
394
395
396
397
398
399 private MofPackage loadMetaModel(final URL metamodelUri)
400 throws Exception
401 {
402 long start = System.currentTimeMillis();
403 if (logger.isDebugEnabled())
404 {
405 logger.debug("creating MetaModel using URL --> '" + metamodelUri + '\'');
406 }
407
408
409
410 ModelPackage metaModelExtent = (ModelPackage)repository.getExtent(metamodelUri.toExternalForm());
411
412 if (metaModelExtent == null)
413 {
414 metaModelExtent = (ModelPackage)repository.createExtent(metamodelUri.toExternalForm());
415 }
416
417 MofPackage metaModelPackage = findPackage(
418 this.metamodelPackage,
419 metaModelExtent);
420 if (metaModelPackage == null)
421 {
422 final XmiReader xmiReader = this.getXMIReaderFactory().createXMIReader();
423 xmiReader.read(
424 metamodelUri.toExternalForm(),
425 metaModelExtent);
426
427
428 metaModelPackage = findPackage(
429 this.metamodelPackage,
430 metaModelExtent);
431 }
432
433 if (logger.isDebugEnabled())
434 {
435 long duration = System.currentTimeMillis() - start;
436 logger.debug("MDRepositoryFacade: loaded metamodel in " + duration + " milliseconds");
437 }
438 return metaModelPackage;
439 }
440
441
442
443
444 public void clear()
445 {
446 this.removeModel(EXTENT_NAME);
447 this.model = null;
448 this.modelFacade = null;
449 }
450
451 private void removeModel(final String modelUri)
452 {
453
454 RefPackage model = repository.getExtent(modelUri);
455 if (model != null)
456 {
457 model.refDelete();
458 }
459 }
460
461
462
463
464
465
466
467
468
469
470 private RefPackage loadModel(
471 final String[] modelUris,
472 final String[] moduleSearchPath,
473 final MofPackage metaModel)
474 throws Exception
475 {
476 if (logger.isDebugEnabled())
477 {
478 logger.debug("loadModel: starting to load model from '" + modelUris[0] + '\'');
479 }
480 long start = System.currentTimeMillis();
481
482 RefPackage model = null;
483 if (modelUris != null)
484 {
485 model = this.createModel(metaModel);
486 final XmiReader xmiReader =
487 this.getXMIReaderFactory().createXMIReader(
488 new MDRXmiReferenceResolver(
489 new RefPackage[] {model},
490 moduleSearchPath));
491 try
492 {
493 final int uriNumber = modelUris.length;
494 for (int ctr = 0; ctr < uriNumber; ctr++)
495 {
496 final String uri = modelUris[ctr];
497 if (uri != null)
498 {
499 xmiReader.read(
500 modelUris[ctr],
501 model);
502 }
503 }
504 }
505 catch (final Throwable throwable)
506 {
507 throw new RepositoryFacadeException(throwable);
508 }
509 if (logger.isDebugEnabled())
510 {
511 logger.debug("read URIs and created model");
512 }
513 }
514
515 if (logger.isDebugEnabled())
516 {
517 long duration = System.currentTimeMillis() - start;
518 logger.debug("loadModel: finished loading model in " + duration + " milliseconds.");
519 }
520
521 return model;
522 }
523
524
525
526
527
528
529
530
531
532
533
534 private RefPackage loadModel(
535 final InputStream[] modelStreams,
536 final String[] uris,
537 final String[] moduleSearchPaths,
538 final MofPackage metaModel)
539 throws Exception
540 {
541 final RefPackage model = this.createModel(metaModel);
542 if (modelStreams != null)
543 {
544 final XmiReader xmiReader =
545 this.getXMIReaderFactory().createXMIReader(
546 new MDRXmiReferenceResolver(
547 new RefPackage[] {model},
548 moduleSearchPaths));
549 try
550 {
551 final int streamNumber = modelStreams.length;
552 for (int ctr = 0; ctr < streamNumber; ctr++)
553 {
554 final InputStream stream = modelStreams[ctr];
555 String uri = null;
556 if (uris != null)
557 {
558 uri = uris[ctr];
559 }
560 if (stream != null)
561 {
562 xmiReader.read(
563 stream,
564 uri,
565 model);
566 }
567 }
568 }
569 catch (final Throwable throwable)
570 {
571 throw new RepositoryFacadeException(throwable);
572 }
573 if (logger.isDebugEnabled())
574 {
575 logger.debug("read URIs and created model");
576 }
577 }
578 return model;
579 }
580
581
582
583
584
585 private static final String EXTENT_NAME = "model";
586
587
588
589
590
591
592
593
594 private RefPackage createModel(final MofPackage metaModel)
595 throws CreationFailedException
596 {
597 RefPackage model = this.repository.getExtent(EXTENT_NAME);
598 if (model != null)
599 {
600 this.removeModel(EXTENT_NAME);
601 }
602 if (logger.isDebugEnabled())
603 {
604 logger.debug("creating the new meta model");
605 }
606 model = repository.createExtent(
607 EXTENT_NAME,
608 metaModel);
609 if (logger.isDebugEnabled())
610 {
611 logger.debug("created model extent");
612 }
613 return model;
614 }
615
616
617
618
619
620
621
622
623 private MofPackage findPackage(
624 final String packageName,
625 final ModelPackage metaModel)
626 {
627 MofPackage mofPackage = null;
628 for (final Iterator iterator = metaModel.getMofPackage().refAllOfClass().iterator(); iterator.hasNext();)
629 {
630 final javax.jmi.model.ModelElement element = (javax.jmi.model.ModelElement)iterator.next();
631 if (element.getName().equals(packageName))
632 {
633 mofPackage = (MofPackage)element;
634 break;
635 }
636 }
637 return mofPackage;
638 }
639 }