001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/crs/configuration/CRSConfiguration.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.crs.configuration; 038 039 import static org.deegree.crs.projections.ProjectionUtils.EPS11; 040 041 import java.io.BufferedWriter; 042 import java.io.File; 043 import java.io.FileWriter; 044 import java.io.IOException; 045 import java.io.InputStream; 046 import java.lang.reflect.Constructor; 047 import java.lang.reflect.InvocationTargetException; 048 import java.util.HashMap; 049 import java.util.LinkedList; 050 import java.util.List; 051 import java.util.Map; 052 import java.util.Properties; 053 054 import org.deegree.crs.configuration.deegree.DeegreeCRSProvider; 055 import org.deegree.crs.configuration.proj4.PROJ4CRSProvider; 056 import org.deegree.crs.coordinatesystems.CoordinateSystem; 057 import org.deegree.crs.coordinatesystems.ProjectedCRS; 058 import org.deegree.crs.exceptions.CRSConfigurationException; 059 import org.deegree.crs.projections.Projection; 060 import org.deegree.framework.log.ILogger; 061 import org.deegree.framework.log.LoggerFactory; 062 import org.deegree.i18n.Messages; 063 064 /** 065 * The <code>CRSConfiguration</code> creates, instantiates and supplies a configured CRS-Provider. Because only one 066 * crs-configuration is needed inside the JVM, this implementation uses a singleton pattern. 067 * <p> 068 * The configuration will try to read the file: crs_providers.properties. It uses following strategie to load this file, 069 * first the root directory (e.g. '/' or WEB-INF/classes ) will be searched. If no file was found there, it will try to 070 * load from the package. The properties file must denote a property with name 'CRS_PROVIDER' followed by a '=' and a 071 * fully qualified name denoting the class (an instance of CRSProvider) which should be available in the classpath. This 072 * class must have an empty constructor. 073 * </p> 074 * 075 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 076 * @author last edited by: $Author: rbezema $ 077 * 078 * @version $Revision: 18308 $, $Date: 2009-07-02 14:40:19 +0200 (Do, 02 Jul 2009) $ 079 */ 080 081 public class CRSConfiguration { 082 private static ILogger LOG = LoggerFactory.getLogger( CRSConfiguration.class ); 083 084 private CRSProvider provider; 085 086 /** 087 * public so servlets can clear it, to avoid memory leaks... 088 */ 089 public static final Map<String, CRSConfiguration> DEFINED_CONFIGURATIONS = new HashMap<String, CRSConfiguration>(); 090 091 private static final String DEFAULT_PROVIDER_CLASS = "org.deegree.crs.configuration.DeegreeCRSProvider"; 092 093 private static String CONFIGURED_DEFAULT_PROVIDER_CLASS = DEFAULT_PROVIDER_CLASS; 094 095 // 096 private final static String PROVIDER_CONFIG = "crs_providers.properties"; 097 098 private static Properties configuredProperties = null; 099 100 static { 101 configuredProperties = new Properties(); 102 LOG.logDebug( "Trying to load configured CRS provider from configuration (/crs_providers.properties)." ); 103 InputStream is = CRSConfiguration.class.getResourceAsStream( "/" + PROVIDER_CONFIG ); 104 if ( is == null ) { 105 LOG.logDebug( "Trying to load configured CRS provider from configuration (org.deegree.crs.configuration.crs_providers.properties)." ); 106 is = CRSConfiguration.class.getResourceAsStream( PROVIDER_CONFIG ); 107 } 108 if ( is == null ) { 109 LOG.logWarning( Messages.getMessage( "CRS_CONFIG_NO_PROVIDER_DEFS_FOUND", PROVIDER_CONFIG ) ); 110 } else { 111 try { 112 configuredProperties.load( is ); 113 configuredProperties.put( "crs.default.configuration", "deegree-crs-configuration.xml" ); 114 String tmp = configuredProperties.getProperty( "CRS_PROVIDER" ); 115 if ( tmp != null && !"".equals( tmp.trim() ) ) { 116 CONFIGURED_DEFAULT_PROVIDER_CLASS = tmp; 117 String crs_configuration = System.getProperty( "crs.configuration" ); 118 if ( crs_configuration != null && !"".equals( crs_configuration ) ) { 119 LOG.logInfo( "Using the supplied crs.configuration property for the crs_configuration location." ); 120 configuredProperties.put( "crs.configuration", crs_configuration ); 121 } 122 } 123 124 } catch ( Exception e ) { 125 LOG.logError( e.getMessage(), e ); 126 } finally { 127 try { 128 is.close(); 129 } catch ( IOException e ) { 130 // no output if the stream can't be closed, just leave it as it is. 131 } 132 } 133 } 134 135 } 136 137 // private static CRSConfiguration CONFIG = null; 138 139 /** 140 * @param provider 141 * to get the CRS's from. 142 */ 143 private CRSConfiguration( CRSProvider provider ) { 144 this.provider = provider; 145 } 146 147 /** 148 * Creates or returns an instance of the CRSConfiguration by trying to instantiate the given provider class. If the 149 * name is null or "" the Provider configured in the 'crs_providers.properties' will be returned. If the 150 * instantiation of this class fails a {@link org.deegree.crs.configuration.deegree.DeegreeCRSProvider} will be 151 * returned. 152 * 153 * @param providerName 154 * the canonical name of the class, e.g. org.deegree.crs.MyProvider 155 * @return an instance of a CRS-Configuration with the configured CRSProvider. 156 * @throws CRSConfigurationException 157 * if --anything-- went wrong while instantiating the CRSProvider. 158 */ 159 public synchronized static CRSConfiguration getCRSConfiguration( String providerName ) { 160 String provName = null; 161 if ( providerName == null || "".equals( providerName.trim() ) ) { 162 provName = CONFIGURED_DEFAULT_PROVIDER_CLASS; 163 } else { 164 provName = providerName.trim(); 165 } 166 LOG.logDebug( "Trying to find a provider for class: " + provName ); 167 if ( DEFINED_CONFIGURATIONS.containsKey( provName ) && DEFINED_CONFIGURATIONS.get( provName ) != null ) { 168 LOG.logDebug( "Found a cached provider for class: " + provName ); 169 return DEFINED_CONFIGURATIONS.get( provName ); 170 } 171 CRSProvider provider = null; 172 173 if ( CONFIGURED_DEFAULT_PROVIDER_CLASS.equals( provName ) 174 && CONFIGURED_DEFAULT_PROVIDER_CLASS.equals( DEFAULT_PROVIDER_CLASS ) ) { 175 provider = new DeegreeCRSProvider( new Properties( configuredProperties ) ); 176 } else { 177 try { 178 // use reflection to instantiate the configured provider. 179 Class<?> t = Class.forName( provName ); 180 t.asSubclass( CRSProvider.class ); 181 LOG.logDebug( "Trying to load configured CRS provider from classname: " + provName ); 182 Constructor<?> constructor = t.getConstructor( Properties.class ); 183 if ( constructor != null ) { 184 provider = (CRSProvider) constructor.newInstance( configuredProperties ); 185 } 186 } catch ( InstantiationException e ) { 187 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 188 } catch ( IllegalAccessException e ) { 189 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 190 } catch ( ClassNotFoundException e ) { 191 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 192 } catch ( SecurityException e ) { 193 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 194 } catch ( NoSuchMethodException e ) { 195 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 196 } catch ( IllegalArgumentException e ) { 197 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 198 } catch ( InvocationTargetException e ) { 199 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, e.getMessage() ), e ); 200 } catch ( Throwable t ) { 201 LOG.logError( Messages.getMessage( "CRS_CONFIG_INSTANTIATION_ERROR", provName, t.getMessage() ), t ); 202 } finally { 203 if ( provider == null ) { 204 LOG.logInfo( "The configured class: " + provName 205 + " was not created. Trying to create a deegree-crs-provider" ); 206 provider = new DeegreeCRSProvider( new Properties( configuredProperties ) ); 207 } 208 } 209 } 210 CRSConfiguration config = new CRSConfiguration( provider ); 211 DEFINED_CONFIGURATIONS.put( provName, config ); 212 LOG.logDebug( "Instantiated a new CRSConfiguration :" + config ); 213 return config; 214 } 215 216 /** 217 * Creates or returns an instance of the CRSConfiguration by reading the DEFAULT property configured in the 218 * 'crs_providers.properties'. If no key is given (or no string could be loaded), the {@link DeegreeCRSProvider} 219 * will be used. 220 * 221 * @return an instance of a CRS-Configuration with the configured CRSProvider. 222 * @throws CRSConfigurationException 223 * if --anything-- went wrong while instantiating the CRSProvider. 224 */ 225 public synchronized static CRSConfiguration getCRSConfiguration() 226 throws CRSConfigurationException { 227 return getCRSConfiguration( null ); 228 } 229 230 /** 231 * Overwrites the crs.configuration property with the given value. 232 * 233 * @param fileName 234 * to set the crs.configuration property to. 235 * 236 * @return the old crs.configuration propert (if any) 237 * @throws CRSConfigurationException 238 * if --anything-- went wrong while instantiating the CRSProvider. 239 */ 240 public synchronized static String setDefaultFileProperty( String fileName ) { 241 return (String) configuredProperties.setProperty( "crs.configuration", fileName ); 242 } 243 244 /** 245 * export the given file to the deegree-crs format. 246 * 247 * @param args 248 * @throws Exception 249 */ 250 public static void main( String[] args ) 251 throws Exception { 252 if ( args.length == 0 ) { 253 outputHelp(); 254 } 255 Map<String, String> params = new HashMap<String, String>( 5 ); 256 for ( int i = 0; i < args.length; i++ ) { 257 String arg = args[i]; 258 if ( arg != null && !"".equals( arg.trim() ) ) { 259 arg = arg.trim(); 260 if ( arg.equalsIgnoreCase( "-?" ) || arg.equalsIgnoreCase( "-h" ) ) { 261 outputHelp(); 262 } else { 263 if ( i + 1 < args.length ) { 264 String val = args[++i]; 265 if ( val != null && !"".equals( val.trim() ) ) { 266 params.put( arg, val.trim() ); 267 } else { 268 System.out.println( "Invalid value for parameter: " + arg ); 269 } 270 } else { 271 System.out.println( "No value for parameter: " + arg ); 272 } 273 } 274 } 275 } 276 String inFormat = params.get( "-inFormat" ); 277 if ( inFormat == null || "".equals( inFormat.trim() ) ) { 278 System.out.println( "No input format (inFormat) defined, setting to proj4" ); 279 inFormat = "proj4"; 280 } 281 String inFile = params.get( "-inFile" ); 282 if ( inFile == null || "".equals( inFile.trim() ) ) { 283 System.out.println( "No input file set, exiting\n" ); 284 outputHelp(); 285 throw new Exception( "No input file set, exiting" ); 286 } 287 // File inputFile = new File( inFile ); 288 289 String outFile = params.get( "-outFile" ); 290 String outFormat = params.get( "-outFormat" ); 291 if ( outFormat == null || "".equals( outFormat.trim() ) ) { 292 System.out.println( "No output format (outFormat) defined, setting to deegree" ); 293 outFormat = "deegree"; 294 } 295 296 String veri = params.get( "-verify" ); 297 boolean verify = ( veri != null && !"".equals( inFile.trim() ) ); 298 299 Properties inProps = new Properties(); 300 inProps.put( "crs.configuration", inFile ); 301 CRSProvider in = new PROJ4CRSProvider( inProps ); 302 if ( "deegree".equalsIgnoreCase( inFormat ) ) { 303 try { 304 in = new DeegreeCRSProvider( new Properties( configuredProperties ) ); 305 } catch ( CRSConfigurationException e ) { 306 e.printStackTrace(); 307 } 308 } 309 310 CRSProvider out = new DeegreeCRSProvider( new Properties( configuredProperties ) ); 311 if ( "proj4".equalsIgnoreCase( outFormat ) ) { 312 out = new PROJ4CRSProvider(); 313 } 314 315 try { 316 List<CoordinateSystem> allSystems = in.getAvailableCRSs(); 317 if ( verify ) { 318 out = new DeegreeCRSProvider( null ); 319 List<CoordinateSystem> notExported = new LinkedList<CoordinateSystem>(); 320 for ( CoordinateSystem inCRS : allSystems ) { 321 if ( inCRS.getType() == CoordinateSystem.PROJECTED_CRS ) { 322 String id = inCRS.getIdentifier(); 323 CoordinateSystem outCRS = out.getCRSByID( id ); 324 // System.out.print( "Getting crs: " + id + " and projection: " + 325 // ((ProjectedCRS)inCRS).getProjection().getDeegreeSpecificName() ); 326 if ( outCRS != null && outCRS.getType() == CoordinateSystem.PROJECTED_CRS ) { 327 // System.out.println( "... [SUCCESS] to retrieve from deegree-config 328 // with projection: " + 329 // ((ProjectedCRS)outCRS).getProjection().getDeegreeSpecificName() ); 330 Projection inProj = ( (ProjectedCRS) inCRS ).getProjection(); 331 Projection outProj = ( (ProjectedCRS) outCRS ).getProjection(); 332 if ( Math.abs( inProj.getProjectionLatitude() - outProj.getProjectionLatitude() ) > EPS11 ) { 333 System.out.println( "For the projection with id: " + id 334 + " the projectionLatitude differs:\n in (" 335 + ( (ProjectedCRS) inCRS ).getProjection().getImplementationName() 336 + "): " + Math.toDegrees( inProj.getProjectionLatitude() ) 337 + "\nout(" 338 + ( (ProjectedCRS) outCRS ).getProjection().getImplementationName() 339 + " with id: " 340 + ( (ProjectedCRS) outCRS ).getProjection().getImplementationName() 341 + "): " + Math.toDegrees( outProj.getProjectionLatitude() ) ); 342 } 343 } else { 344 notExported.add( inCRS ); 345 System.out.println( id + " [FAILED] to retrieve from deegree-config." ); 346 } 347 } 348 } 349 if ( notExported.size() > 0 ) { 350 StringBuilder sb = new StringBuilder( notExported.size() * 2000 ); 351 out.export( sb, allSystems ); 352 if ( outFile != null && !"".equals( outFile.trim() ) ) { 353 File outputFile = new File( outFile ); 354 BufferedWriter writer = new BufferedWriter( new FileWriter( outputFile ) ); 355 writer.write( sb.toString() ); 356 writer.flush(); 357 writer.close(); 358 } else { 359 System.out.println( sb.toString() ); 360 } 361 } 362 } else { 363 364 StringBuilder sb = new StringBuilder( allSystems.size() * 2000 ); 365 out.export( sb, allSystems ); 366 if ( outFile != null && !"".equals( outFile.trim() ) ) { 367 File outputFile = new File( outFile ); 368 BufferedWriter writer = new BufferedWriter( new FileWriter( outputFile ) ); 369 writer.write( sb.toString() ); 370 writer.flush(); 371 writer.close(); 372 } else { 373 System.out.println( sb.toString() ); 374 } 375 } 376 } catch ( CRSConfigurationException e ) { 377 e.printStackTrace(); 378 } catch ( IOException e ) { 379 e.printStackTrace(); 380 } 381 382 // CRSConfiguration config = new CRSConfiguration( 383 } 384 385 private static void outputHelp() { 386 StringBuilder sb = new StringBuilder(); 387 sb.append( "The CRSConfiguration program can be used to create a deegree-crs-configuration, from other crs definition-formats. Following parameters are supported:\n" ); 388 sb.append( "-inFile the /path/to/crs-definitions-file\n" ); 389 sb.append( "-inFormat the format of the input file, valid values are proj4(default),deegree \n" ); 390 sb.append( "-outFormat the format of the output file, valid values are deegree (default)\n" ); 391 sb.append( "-outFile the /path/to/the/output/file or standard output if not supplied.\n" ); 392 sb.append( "[-verify] checks the projection parameters of the inFormat against the deegree configuration.\n" ); 393 sb.append( "-?|-h output this text\n" ); 394 sb.append( "example usage: java -cp deegree.jar org.deegree.crs.configuration.CRSConfiguration -inFormat 'proj4' -inFile '/home/proj4/nad/epsg' -outFormat 'deegree' -outFile '/home/deegree/crs-definitions.xml'\n" ); 395 System.out.println( sb.toString() ); 396 System.exit( 1 ); 397 } 398 399 /** 400 * @return the crs provider. 401 */ 402 public final CRSProvider getProvider() { 403 return provider; 404 } 405 406 @Override 407 public String toString() { 408 return "CRSConfiguration is using " 409 + ( ( provider == null ) ? "no crs provider, this is strange." 410 : "crs provider: " + provider.getClass().getCanonicalName() ); 411 } 412 }