001package org.andromda.repositories.emf; 002 003import java.io.InputStream; 004import java.net.URL; 005import java.util.Date; 006import java.util.HashMap; 007import java.util.List; 008import java.util.Map; 009import org.andromda.core.common.AndroMDALogger; 010import org.andromda.core.common.ResourceUtils; 011import org.apache.log4j.Logger; 012import org.eclipse.emf.common.util.URI; 013import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl; 014 015/** 016 * Extends the default URIConverterImpl to be able to discover the physical path of URIs when 017 * given the moduleSearchPaths. 018 * 019 * @author Chad Brandon 020 * @author Bob Fields 021 */ 022public class EMFURIConverter 023 extends ExtensibleURIConverterImpl 024 // Use URIConverterImpl for UML2 2.x 025{ 026 /** 027 * Creates a new instance of EMFURIConverter taking the <code>moduleSearchPaths</code> 028 * and the existing URI Map as arguments. These are the paths used to attempt to normalize a given URI during 029 * the call to {@link #normalize(URI)} provided that it couldn't be found in the normal manner. 030 * 031 * @param moduleSearchPaths the paths to search for modules. 032 * @param uriMap 033 */ 034 public EMFURIConverter(final List<String> moduleSearchPaths, Map<URI, URI> uriMap) 035 { 036 this.normalizedUris = uriMap; 037 this.moduleSearchPaths = moduleSearchPaths; 038 if (logger.isDebugEnabled()) 039 { 040 for (final String path : moduleSearchPaths) 041 { 042 logger.debug("Model search path:" + path); 043 } 044 } 045 } 046 047 /** 048 * Creates a new instance of EMFURIConverter taking the <code>moduleSearchPaths</code> 049 * as an argument. These are the paths used to attempt to normalize a given URI during 050 * the call to {@link #normalize(URI)} provided that it couldn't be found in the normal manner. 051 * 052 * @param moduleSearchPaths the paths to search for modules. 053 */ 054 public EMFURIConverter(final List<String> moduleSearchPaths) 055 { 056 this.moduleSearchPaths = moduleSearchPaths; 057 if (logger.isDebugEnabled()) 058 { 059 for (final String path : moduleSearchPaths) 060 { 061 logger.debug("Model search path:" + path); 062 } 063 } 064 } 065 066 /** 067 * Stores the module search paths. 068 */ 069 private List<String> moduleSearchPaths; 070 071 /** 072 * Stores the URIs that have been normalized. 073 */ 074 private Map<URI, URI> normalizedUris = new HashMap<URI, URI>(); 075 076 /** 077 * The logger instance. 078 */ 079 private static final Logger logger = Logger.getLogger(EMFURIConverter.class); 080 081 /** 082 * Overridden to provide the normalization of uris given the module search paths. 083 * 084 * @see org.eclipse.emf.ecore.resource.URIConverter#normalize(org.eclipse.emf.common.util.URI) 085 */ 086 public URI normalize(final URI uri) 087 { 088 URI normalizedUri = super.normalize(uri); 089 if (normalizedUri.equals(uri)) 090 { 091 if (this.moduleSearchPaths != null) 092 { 093 if (!this.normalizedUris.containsKey(uri)) 094 { 095 final String resourceName = uri.toString().replaceAll( 096 ".*(\\\\+|/)", 097 ""); 098 for (final String searchPath : moduleSearchPaths) 099 { 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}