1 package org.andromda.repositories.emf;
2
3 import java.io.InputStream;
4 import java.net.URL;
5 import java.util.Date;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9 import org.andromda.core.common.AndroMDALogger;
10 import org.andromda.core.common.ResourceUtils;
11 import org.apache.log4j.Logger;
12 import org.eclipse.emf.common.util.URI;
13 import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl;
14
15 /**
16 * Extends the default URIConverterImpl to be able to discover the physical path of URIs when
17 * given the moduleSearchPaths.
18 *
19 * @author Chad Brandon
20 * @author Bob Fields
21 */
22 public class EMFURIConverter
23 extends ExtensibleURIConverterImpl
24 // Use URIConverterImpl for UML2 2.x
25 {
26 /**
27 * Creates a new instance of EMFURIConverter taking the <code>moduleSearchPaths</code>
28 * and the existing URI Map as arguments. These are the paths used to attempt to normalize a given URI during
29 * the call to {@link #normalize(URI)} provided that it couldn't be found in the normal manner.
30 *
31 * @param moduleSearchPaths the paths to search for modules.
32 * @param uriMap
33 */
34 public EMFURIConverter(final List<String> moduleSearchPaths, Map<URI, URI> uriMap)
35 {
36 this.normalizedUris = uriMap;
37 this.moduleSearchPaths = moduleSearchPaths;
38 if (logger.isDebugEnabled())
39 {
40 for (final String path : moduleSearchPaths)
41 {
42 logger.debug("Model search path:" + path);
43 }
44 }
45 }
46
47 /**
48 * Creates a new instance of EMFURIConverter taking the <code>moduleSearchPaths</code>
49 * as an argument. These are the paths used to attempt to normalize a given URI during
50 * the call to {@link #normalize(URI)} provided that it couldn't be found in the normal manner.
51 *
52 * @param moduleSearchPaths the paths to search for modules.
53 */
54 public EMFURIConverter(final List<String> moduleSearchPaths)
55 {
56 this.moduleSearchPaths = moduleSearchPaths;
57 if (logger.isDebugEnabled())
58 {
59 for (final String path : moduleSearchPaths)
60 {
61 logger.debug("Model search path:" + path);
62 }
63 }
64 }
65
66 /**
67 * Stores the module search paths.
68 */
69 private List<String> moduleSearchPaths;
70
71 /**
72 * Stores the URIs that have been normalized.
73 */
74 private Map<URI, URI> normalizedUris = new HashMap<URI, URI>();
75
76 /**
77 * The logger instance.
78 */
79 private static final Logger logger = Logger.getLogger(EMFURIConverter.class);
80
81 /**
82 * Overridden to provide the normalization of uris given the module search paths.
83 *
84 * @see org.eclipse.emf.ecore.resource.URIConverter#normalize(org.eclipse.emf.common.util.URI)
85 */
86 public URI normalize(final URI uri)
87 {
88 URI normalizedUri = super.normalize(uri);
89 if (normalizedUri.equals(uri))
90 {
91 if (this.moduleSearchPaths != null)
92 {
93 if (!this.normalizedUris.containsKey(uri))
94 {
95 final String resourceName = uri.toString().replaceAll(
96 ".*(\\\\+|/)",
97 "");
98 for (final String searchPath : moduleSearchPaths)
99 {
100 Date now1 = new Date();
101 final URI fileURI = EMFRepositoryFacadeUtils.createUri(ResourceUtils.normalizePath(searchPath));
102 long ms1 = new Date().getTime() - now1.getTime();
103 if (fileURI != null && fileURI.lastSegment() != null && fileURI.lastSegment().equals(resourceName))
104 {
105 String ms = (ms1 > 100 ? ms1 + " ms" : "");
106 AndroMDALogger.info("referenced model --> '" + fileURI + "' " + ms);
107 normalizedUri = fileURI;
108 this.normalizedUris.put(
109 uri,
110 normalizedUri);
111 break;
112 }
113
114 final String completePath = ResourceUtils.normalizePath(searchPath + '/' + resourceName);
115
116 try
117 {
118 Date now = new Date();
119 InputStream stream;
120 URL url = ResourceUtils.toURL(completePath);
121 if (url != null)
122 {
123 try
124 {
125 stream = url.openStream();
126 stream.close();
127 long ms2 = new Date().getTime() - now.getTime();
128 String ms = (ms2 > 100 ? ms2 + " ms" : "");
129 AndroMDALogger.info("referenced model --> '" + url + "' " + ms);
130 }
131 catch (final Exception exception)
132 {
133 url = null;
134 }
135 finally
136 {
137 stream = null;
138 }
139 if (url != null)
140 {
141 long ms2 = new Date().getTime() - now.getTime();
142 normalizedUri = EMFRepositoryFacadeUtils.createUri(url.toString());
143 this.normalizedUris.put(
144 uri,
145 normalizedUri);
146 if (AndroMDALogger.isDebugEnabled())
147 {
148 AndroMDALogger.debug("loaded model --> '" + url + "' " + ms2 + " ms");
149 }
150 break;
151 }
152 }
153 }
154 catch (final Exception exception)
155 {
156 logger.debug(
157 "Caught exception in EMFURIConverter",
158 exception);
159 }
160 long ms2 = new Date().getTime() - now1.getTime();
161 String ms = (ms2 > 100 ? ms2 + " ms" : "");
162 if (AndroMDALogger.isDebugEnabled())
163 {
164 AndroMDALogger.debug("loaded model --> '" + fileURI + "' " + ms);
165 }
166 }
167
168 // - if the normalized URI isn't part of the module search path,
169 // still store it so we don't continue to look it up each time (which is really slow)
170 if (!this.normalizedUris.containsKey(uri))
171 {
172 this.normalizedUris.put(
173 uri,
174 normalizedUri);
175 }
176 }
177 else
178 {
179 normalizedUri = this.normalizedUris.get(uri);
180 }
181 }
182 }
183
184 return normalizedUri;
185 }
186 }